xref: /reactos/dll/3rdparty/mbedtls/bignum.c (revision d9e6c9b5)
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 
68*d9e6c9b5SThomas Faber /* Implementation that should never be optimized out by the compiler */
69*d9e6c9b5SThomas Faber static void mbedtls_zeroize( void *v, size_t n ) {
70*d9e6c9b5SThomas Faber     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
71*d9e6c9b5SThomas Faber }
72*d9e6c9b5SThomas 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 
323c2c66affSColin Finck /*
324c2c66affSColin Finck  * Set a bit to a specific value of 0 or 1
325c2c66affSColin Finck  */
326c2c66affSColin Finck int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
327c2c66affSColin Finck {
328c2c66affSColin Finck     int ret = 0;
329c2c66affSColin Finck     size_t off = pos / biL;
330c2c66affSColin Finck     size_t idx = pos % biL;
331c2c66affSColin Finck 
332c2c66affSColin Finck     if( val != 0 && val != 1 )
333c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
334c2c66affSColin Finck 
335c2c66affSColin Finck     if( X->n * biL <= pos )
336c2c66affSColin Finck     {
337c2c66affSColin Finck         if( val == 0 )
338c2c66affSColin Finck             return( 0 );
339c2c66affSColin Finck 
340c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
341c2c66affSColin Finck     }
342c2c66affSColin Finck 
343c2c66affSColin Finck     X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
344c2c66affSColin Finck     X->p[off] |= (mbedtls_mpi_uint) val << idx;
345c2c66affSColin Finck 
346c2c66affSColin Finck cleanup:
347c2c66affSColin Finck 
348c2c66affSColin Finck     return( ret );
349c2c66affSColin Finck }
350c2c66affSColin Finck 
351c2c66affSColin Finck /*
352c2c66affSColin Finck  * Return the number of less significant zero-bits
353c2c66affSColin Finck  */
354c2c66affSColin Finck size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
355c2c66affSColin Finck {
356c2c66affSColin Finck     size_t i, j, count = 0;
357c2c66affSColin Finck 
358c2c66affSColin Finck     for( i = 0; i < X->n; i++ )
359c2c66affSColin Finck         for( j = 0; j < biL; j++, count++ )
360c2c66affSColin Finck             if( ( ( X->p[i] >> j ) & 1 ) != 0 )
361c2c66affSColin Finck                 return( count );
362c2c66affSColin Finck 
363c2c66affSColin Finck     return( 0 );
364c2c66affSColin Finck }
365c2c66affSColin Finck 
366c2c66affSColin Finck /*
367c2c66affSColin Finck  * Count leading zero bits in a given integer
368c2c66affSColin Finck  */
369c2c66affSColin Finck static size_t mbedtls_clz( const mbedtls_mpi_uint x )
370c2c66affSColin Finck {
371c2c66affSColin Finck     size_t j;
372c2c66affSColin Finck     mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
373c2c66affSColin Finck 
374c2c66affSColin Finck     for( j = 0; j < biL; j++ )
375c2c66affSColin Finck     {
376c2c66affSColin Finck         if( x & mask ) break;
377c2c66affSColin Finck 
378c2c66affSColin Finck         mask >>= 1;
379c2c66affSColin Finck     }
380c2c66affSColin Finck 
381c2c66affSColin Finck     return j;
382c2c66affSColin Finck }
383c2c66affSColin Finck 
384c2c66affSColin Finck /*
385c2c66affSColin Finck  * Return the number of bits
386c2c66affSColin Finck  */
387c2c66affSColin Finck size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
388c2c66affSColin Finck {
389c2c66affSColin Finck     size_t i, j;
390c2c66affSColin Finck 
391c2c66affSColin Finck     if( X->n == 0 )
392c2c66affSColin Finck         return( 0 );
393c2c66affSColin Finck 
394c2c66affSColin Finck     for( i = X->n - 1; i > 0; i-- )
395c2c66affSColin Finck         if( X->p[i] != 0 )
396c2c66affSColin Finck             break;
397c2c66affSColin Finck 
398c2c66affSColin Finck     j = biL - mbedtls_clz( X->p[i] );
399c2c66affSColin Finck 
400c2c66affSColin Finck     return( ( i * biL ) + j );
401c2c66affSColin Finck }
402c2c66affSColin Finck 
403c2c66affSColin Finck /*
404c2c66affSColin Finck  * Return the total size in bytes
405c2c66affSColin Finck  */
406c2c66affSColin Finck size_t mbedtls_mpi_size( const mbedtls_mpi *X )
407c2c66affSColin Finck {
408c2c66affSColin Finck     return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
409c2c66affSColin Finck }
410c2c66affSColin Finck 
411c2c66affSColin Finck /*
412c2c66affSColin Finck  * Convert an ASCII character to digit value
413c2c66affSColin Finck  */
414c2c66affSColin Finck static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
415c2c66affSColin Finck {
416c2c66affSColin Finck     *d = 255;
417c2c66affSColin Finck 
418c2c66affSColin Finck     if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
419c2c66affSColin Finck     if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
420c2c66affSColin Finck     if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
421c2c66affSColin Finck 
422c2c66affSColin Finck     if( *d >= (mbedtls_mpi_uint) radix )
423c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
424c2c66affSColin Finck 
425c2c66affSColin Finck     return( 0 );
426c2c66affSColin Finck }
427c2c66affSColin Finck 
428c2c66affSColin Finck /*
429c2c66affSColin Finck  * Import from an ASCII string
430c2c66affSColin Finck  */
431c2c66affSColin Finck int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
432c2c66affSColin Finck {
433c2c66affSColin Finck     int ret;
434c2c66affSColin Finck     size_t i, j, slen, n;
435c2c66affSColin Finck     mbedtls_mpi_uint d;
436c2c66affSColin Finck     mbedtls_mpi T;
437c2c66affSColin Finck 
438c2c66affSColin Finck     if( radix < 2 || radix > 16 )
439c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
440c2c66affSColin Finck 
441c2c66affSColin Finck     mbedtls_mpi_init( &T );
442c2c66affSColin Finck 
443c2c66affSColin Finck     slen = strlen( s );
444c2c66affSColin Finck 
445c2c66affSColin Finck     if( radix == 16 )
446c2c66affSColin Finck     {
447c2c66affSColin Finck         if( slen > MPI_SIZE_T_MAX >> 2 )
448c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
449c2c66affSColin Finck 
450c2c66affSColin Finck         n = BITS_TO_LIMBS( slen << 2 );
451c2c66affSColin Finck 
452c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
453c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
454c2c66affSColin Finck 
455c2c66affSColin Finck         for( i = slen, j = 0; i > 0; i--, j++ )
456c2c66affSColin Finck         {
457c2c66affSColin Finck             if( i == 1 && s[i - 1] == '-' )
458c2c66affSColin Finck             {
459c2c66affSColin Finck                 X->s = -1;
460c2c66affSColin Finck                 break;
461c2c66affSColin Finck             }
462c2c66affSColin Finck 
463c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
464c2c66affSColin Finck             X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
465c2c66affSColin Finck         }
466c2c66affSColin Finck     }
467c2c66affSColin Finck     else
468c2c66affSColin Finck     {
469c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
470c2c66affSColin Finck 
471c2c66affSColin Finck         for( i = 0; i < slen; i++ )
472c2c66affSColin Finck         {
473c2c66affSColin Finck             if( i == 0 && s[i] == '-' )
474c2c66affSColin Finck             {
475c2c66affSColin Finck                 X->s = -1;
476c2c66affSColin Finck                 continue;
477c2c66affSColin Finck             }
478c2c66affSColin Finck 
479c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
480c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
481c2c66affSColin Finck 
482c2c66affSColin Finck             if( X->s == 1 )
483c2c66affSColin Finck             {
484c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
485c2c66affSColin Finck             }
486c2c66affSColin Finck             else
487c2c66affSColin Finck             {
488c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) );
489c2c66affSColin Finck             }
490c2c66affSColin Finck         }
491c2c66affSColin Finck     }
492c2c66affSColin Finck 
493c2c66affSColin Finck cleanup:
494c2c66affSColin Finck 
495c2c66affSColin Finck     mbedtls_mpi_free( &T );
496c2c66affSColin Finck 
497c2c66affSColin Finck     return( ret );
498c2c66affSColin Finck }
499c2c66affSColin Finck 
500c2c66affSColin Finck /*
501c2c66affSColin Finck  * Helper to write the digits high-order first
502c2c66affSColin Finck  */
503c2c66affSColin Finck static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p )
504c2c66affSColin Finck {
505c2c66affSColin Finck     int ret;
506c2c66affSColin Finck     mbedtls_mpi_uint r;
507c2c66affSColin Finck 
508c2c66affSColin Finck     if( radix < 2 || radix > 16 )
509c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
510c2c66affSColin Finck 
511c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
512c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
513c2c66affSColin Finck 
514c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( X, 0 ) != 0 )
515c2c66affSColin Finck         MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) );
516c2c66affSColin Finck 
517c2c66affSColin Finck     if( r < 10 )
518c2c66affSColin Finck         *(*p)++ = (char)( r + 0x30 );
519c2c66affSColin Finck     else
520c2c66affSColin Finck         *(*p)++ = (char)( r + 0x37 );
521c2c66affSColin Finck 
522c2c66affSColin Finck cleanup:
523c2c66affSColin Finck 
524c2c66affSColin Finck     return( ret );
525c2c66affSColin Finck }
526c2c66affSColin Finck 
527c2c66affSColin Finck /*
528c2c66affSColin Finck  * Export into an ASCII string
529c2c66affSColin Finck  */
530c2c66affSColin Finck int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
531c2c66affSColin Finck                               char *buf, size_t buflen, size_t *olen )
532c2c66affSColin Finck {
533c2c66affSColin Finck     int ret = 0;
534c2c66affSColin Finck     size_t n;
535c2c66affSColin Finck     char *p;
536c2c66affSColin Finck     mbedtls_mpi T;
537c2c66affSColin Finck 
538c2c66affSColin Finck     if( radix < 2 || radix > 16 )
539c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
540c2c66affSColin Finck 
541c2c66affSColin Finck     n = mbedtls_mpi_bitlen( X );
542c2c66affSColin Finck     if( radix >=  4 ) n >>= 1;
543c2c66affSColin Finck     if( radix >= 16 ) n >>= 1;
544c2c66affSColin Finck     /*
545c2c66affSColin Finck      * Round up the buffer length to an even value to ensure that there is
546c2c66affSColin Finck      * enough room for hexadecimal values that can be represented in an odd
547c2c66affSColin Finck      * number of digits.
548c2c66affSColin Finck      */
549c2c66affSColin Finck     n += 3 + ( ( n + 1 ) & 1 );
550c2c66affSColin Finck 
551c2c66affSColin Finck     if( buflen < n )
552c2c66affSColin Finck     {
553c2c66affSColin Finck         *olen = n;
554c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
555c2c66affSColin Finck     }
556c2c66affSColin Finck 
557c2c66affSColin Finck     p = buf;
558c2c66affSColin Finck     mbedtls_mpi_init( &T );
559c2c66affSColin Finck 
560c2c66affSColin Finck     if( X->s == -1 )
561c2c66affSColin Finck         *p++ = '-';
562c2c66affSColin Finck 
563c2c66affSColin Finck     if( radix == 16 )
564c2c66affSColin Finck     {
565c2c66affSColin Finck         int c;
566c2c66affSColin Finck         size_t i, j, k;
567c2c66affSColin Finck 
568c2c66affSColin Finck         for( i = X->n, k = 0; i > 0; i-- )
569c2c66affSColin Finck         {
570c2c66affSColin Finck             for( j = ciL; j > 0; j-- )
571c2c66affSColin Finck             {
572c2c66affSColin Finck                 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
573c2c66affSColin Finck 
574c2c66affSColin Finck                 if( c == 0 && k == 0 && ( i + j ) != 2 )
575c2c66affSColin Finck                     continue;
576c2c66affSColin Finck 
577c2c66affSColin Finck                 *(p++) = "0123456789ABCDEF" [c / 16];
578c2c66affSColin Finck                 *(p++) = "0123456789ABCDEF" [c % 16];
579c2c66affSColin Finck                 k = 1;
580c2c66affSColin Finck             }
581c2c66affSColin Finck         }
582c2c66affSColin Finck     }
583c2c66affSColin Finck     else
584c2c66affSColin Finck     {
585c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
586c2c66affSColin Finck 
587c2c66affSColin Finck         if( T.s == -1 )
588c2c66affSColin Finck             T.s = 1;
589c2c66affSColin Finck 
590c2c66affSColin Finck         MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
591c2c66affSColin Finck     }
592c2c66affSColin Finck 
593c2c66affSColin Finck     *p++ = '\0';
594c2c66affSColin Finck     *olen = p - buf;
595c2c66affSColin Finck 
596c2c66affSColin Finck cleanup:
597c2c66affSColin Finck 
598c2c66affSColin Finck     mbedtls_mpi_free( &T );
599c2c66affSColin Finck 
600c2c66affSColin Finck     return( ret );
601c2c66affSColin Finck }
602c2c66affSColin Finck 
603c2c66affSColin Finck #if defined(MBEDTLS_FS_IO)
604c2c66affSColin Finck /*
605c2c66affSColin Finck  * Read X from an opened file
606c2c66affSColin Finck  */
607c2c66affSColin Finck int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
608c2c66affSColin Finck {
609c2c66affSColin Finck     mbedtls_mpi_uint d;
610c2c66affSColin Finck     size_t slen;
611c2c66affSColin Finck     char *p;
612c2c66affSColin Finck     /*
613c2c66affSColin Finck      * Buffer should have space for (short) label and decimal formatted MPI,
614c2c66affSColin Finck      * newline characters and '\0'
615c2c66affSColin Finck      */
616c2c66affSColin Finck     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
617c2c66affSColin Finck 
618c2c66affSColin Finck     memset( s, 0, sizeof( s ) );
619c2c66affSColin Finck     if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
620c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
621c2c66affSColin Finck 
622c2c66affSColin Finck     slen = strlen( s );
623c2c66affSColin Finck     if( slen == sizeof( s ) - 2 )
624c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
625c2c66affSColin Finck 
626c2c66affSColin Finck     if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
627c2c66affSColin Finck     if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
628c2c66affSColin Finck 
629c2c66affSColin Finck     p = s + slen;
630c2c66affSColin Finck     while( p-- > s )
631c2c66affSColin Finck         if( mpi_get_digit( &d, radix, *p ) != 0 )
632c2c66affSColin Finck             break;
633c2c66affSColin Finck 
634c2c66affSColin Finck     return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
635c2c66affSColin Finck }
636c2c66affSColin Finck 
637c2c66affSColin Finck /*
638c2c66affSColin Finck  * Write X into an opened file (or stdout if fout == NULL)
639c2c66affSColin Finck  */
640c2c66affSColin Finck int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
641c2c66affSColin Finck {
642c2c66affSColin Finck     int ret;
643c2c66affSColin Finck     size_t n, slen, plen;
644c2c66affSColin Finck     /*
645c2c66affSColin Finck      * Buffer should have space for (short) label and decimal formatted MPI,
646c2c66affSColin Finck      * newline characters and '\0'
647c2c66affSColin Finck      */
648c2c66affSColin Finck     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
649c2c66affSColin Finck 
650c2c66affSColin Finck     memset( s, 0, sizeof( s ) );
651c2c66affSColin Finck 
652c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
653c2c66affSColin Finck 
654c2c66affSColin Finck     if( p == NULL ) p = "";
655c2c66affSColin Finck 
656c2c66affSColin Finck     plen = strlen( p );
657c2c66affSColin Finck     slen = strlen( s );
658c2c66affSColin Finck     s[slen++] = '\r';
659c2c66affSColin Finck     s[slen++] = '\n';
660c2c66affSColin Finck 
661c2c66affSColin Finck     if( fout != NULL )
662c2c66affSColin Finck     {
663c2c66affSColin Finck         if( fwrite( p, 1, plen, fout ) != plen ||
664c2c66affSColin Finck             fwrite( s, 1, slen, fout ) != slen )
665c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
666c2c66affSColin Finck     }
667c2c66affSColin Finck     else
668c2c66affSColin Finck         mbedtls_printf( "%s%s", p, s );
669c2c66affSColin Finck 
670c2c66affSColin Finck cleanup:
671c2c66affSColin Finck 
672c2c66affSColin Finck     return( ret );
673c2c66affSColin Finck }
674c2c66affSColin Finck #endif /* MBEDTLS_FS_IO */
675c2c66affSColin Finck 
676c2c66affSColin Finck /*
677c2c66affSColin Finck  * Import X from unsigned binary data, big endian
678c2c66affSColin Finck  */
679c2c66affSColin Finck int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
680c2c66affSColin Finck {
681c2c66affSColin Finck     int ret;
682*d9e6c9b5SThomas Faber     size_t i, j;
683*d9e6c9b5SThomas Faber     size_t const limbs = CHARS_TO_LIMBS( buflen );
684c2c66affSColin Finck 
685*d9e6c9b5SThomas Faber     /* Ensure that target MPI has exactly the necessary number of limbs */
686*d9e6c9b5SThomas Faber     if( X->n != limbs )
687*d9e6c9b5SThomas Faber     {
688*d9e6c9b5SThomas Faber         mbedtls_mpi_free( X );
689*d9e6c9b5SThomas Faber         mbedtls_mpi_init( X );
690*d9e6c9b5SThomas Faber         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) );
691*d9e6c9b5SThomas Faber     }
692c2c66affSColin Finck 
693c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
694c2c66affSColin Finck 
695*d9e6c9b5SThomas Faber     for( i = buflen, j = 0; i > 0; i--, j++ )
696c2c66affSColin Finck         X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3);
697c2c66affSColin Finck 
698c2c66affSColin Finck cleanup:
699c2c66affSColin Finck 
700c2c66affSColin Finck     return( ret );
701c2c66affSColin Finck }
702c2c66affSColin Finck 
703c2c66affSColin Finck /*
704c2c66affSColin Finck  * Export X into unsigned binary data, big endian
705c2c66affSColin Finck  */
706c2c66affSColin Finck int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen )
707c2c66affSColin Finck {
708c2c66affSColin Finck     size_t i, j, n;
709c2c66affSColin Finck 
710c2c66affSColin Finck     n = mbedtls_mpi_size( X );
711c2c66affSColin Finck 
712c2c66affSColin Finck     if( buflen < n )
713c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
714c2c66affSColin Finck 
715c2c66affSColin Finck     memset( buf, 0, buflen );
716c2c66affSColin Finck 
717c2c66affSColin Finck     for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
718c2c66affSColin Finck         buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
719c2c66affSColin Finck 
720c2c66affSColin Finck     return( 0 );
721c2c66affSColin Finck }
722c2c66affSColin Finck 
723c2c66affSColin Finck /*
724c2c66affSColin Finck  * Left-shift: X <<= count
725c2c66affSColin Finck  */
726c2c66affSColin Finck int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
727c2c66affSColin Finck {
728c2c66affSColin Finck     int ret;
729c2c66affSColin Finck     size_t i, v0, t1;
730c2c66affSColin Finck     mbedtls_mpi_uint r0 = 0, r1;
731c2c66affSColin Finck 
732c2c66affSColin Finck     v0 = count / (biL    );
733c2c66affSColin Finck     t1 = count & (biL - 1);
734c2c66affSColin Finck 
735c2c66affSColin Finck     i = mbedtls_mpi_bitlen( X ) + count;
736c2c66affSColin Finck 
737c2c66affSColin Finck     if( X->n * biL < i )
738c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
739c2c66affSColin Finck 
740c2c66affSColin Finck     ret = 0;
741c2c66affSColin Finck 
742c2c66affSColin Finck     /*
743c2c66affSColin Finck      * shift by count / limb_size
744c2c66affSColin Finck      */
745c2c66affSColin Finck     if( v0 > 0 )
746c2c66affSColin Finck     {
747c2c66affSColin Finck         for( i = X->n; i > v0; i-- )
748c2c66affSColin Finck             X->p[i - 1] = X->p[i - v0 - 1];
749c2c66affSColin Finck 
750c2c66affSColin Finck         for( ; i > 0; i-- )
751c2c66affSColin Finck             X->p[i - 1] = 0;
752c2c66affSColin Finck     }
753c2c66affSColin Finck 
754c2c66affSColin Finck     /*
755c2c66affSColin Finck      * shift by count % limb_size
756c2c66affSColin Finck      */
757c2c66affSColin Finck     if( t1 > 0 )
758c2c66affSColin Finck     {
759c2c66affSColin Finck         for( i = v0; i < X->n; i++ )
760c2c66affSColin Finck         {
761c2c66affSColin Finck             r1 = X->p[i] >> (biL - t1);
762c2c66affSColin Finck             X->p[i] <<= t1;
763c2c66affSColin Finck             X->p[i] |= r0;
764c2c66affSColin Finck             r0 = r1;
765c2c66affSColin Finck         }
766c2c66affSColin Finck     }
767c2c66affSColin Finck 
768c2c66affSColin Finck cleanup:
769c2c66affSColin Finck 
770c2c66affSColin Finck     return( ret );
771c2c66affSColin Finck }
772c2c66affSColin Finck 
773c2c66affSColin Finck /*
774c2c66affSColin Finck  * Right-shift: X >>= count
775c2c66affSColin Finck  */
776c2c66affSColin Finck int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
777c2c66affSColin Finck {
778c2c66affSColin Finck     size_t i, v0, v1;
779c2c66affSColin Finck     mbedtls_mpi_uint r0 = 0, r1;
780c2c66affSColin Finck 
781c2c66affSColin Finck     v0 = count /  biL;
782c2c66affSColin Finck     v1 = count & (biL - 1);
783c2c66affSColin Finck 
784c2c66affSColin Finck     if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
785c2c66affSColin Finck         return mbedtls_mpi_lset( X, 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 = 0; i < X->n - v0; i++ )
793c2c66affSColin Finck             X->p[i] = X->p[i + v0];
794c2c66affSColin Finck 
795c2c66affSColin Finck         for( ; i < X->n; i++ )
796c2c66affSColin Finck             X->p[i] = 0;
797c2c66affSColin Finck     }
798c2c66affSColin Finck 
799c2c66affSColin Finck     /*
800c2c66affSColin Finck      * shift by count % limb_size
801c2c66affSColin Finck      */
802c2c66affSColin Finck     if( v1 > 0 )
803c2c66affSColin Finck     {
804c2c66affSColin Finck         for( i = X->n; i > 0; i-- )
805c2c66affSColin Finck         {
806c2c66affSColin Finck             r1 = X->p[i - 1] << (biL - v1);
807c2c66affSColin Finck             X->p[i - 1] >>= v1;
808c2c66affSColin Finck             X->p[i - 1] |= r0;
809c2c66affSColin Finck             r0 = r1;
810c2c66affSColin Finck         }
811c2c66affSColin Finck     }
812c2c66affSColin Finck 
813c2c66affSColin Finck     return( 0 );
814c2c66affSColin Finck }
815c2c66affSColin Finck 
816c2c66affSColin Finck /*
817c2c66affSColin Finck  * Compare unsigned values
818c2c66affSColin Finck  */
819c2c66affSColin Finck int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
820c2c66affSColin Finck {
821c2c66affSColin Finck     size_t i, j;
822c2c66affSColin Finck 
823c2c66affSColin Finck     for( i = X->n; i > 0; i-- )
824c2c66affSColin Finck         if( X->p[i - 1] != 0 )
825c2c66affSColin Finck             break;
826c2c66affSColin Finck 
827c2c66affSColin Finck     for( j = Y->n; j > 0; j-- )
828c2c66affSColin Finck         if( Y->p[j - 1] != 0 )
829c2c66affSColin Finck             break;
830c2c66affSColin Finck 
831c2c66affSColin Finck     if( i == 0 && j == 0 )
832c2c66affSColin Finck         return( 0 );
833c2c66affSColin Finck 
834c2c66affSColin Finck     if( i > j ) return(  1 );
835c2c66affSColin Finck     if( j > i ) return( -1 );
836c2c66affSColin Finck 
837c2c66affSColin Finck     for( ; i > 0; i-- )
838c2c66affSColin Finck     {
839c2c66affSColin Finck         if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
840c2c66affSColin Finck         if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
841c2c66affSColin Finck     }
842c2c66affSColin Finck 
843c2c66affSColin Finck     return( 0 );
844c2c66affSColin Finck }
845c2c66affSColin Finck 
846c2c66affSColin Finck /*
847c2c66affSColin Finck  * Compare signed values
848c2c66affSColin Finck  */
849c2c66affSColin Finck int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
850c2c66affSColin Finck {
851c2c66affSColin Finck     size_t i, j;
852c2c66affSColin Finck 
853c2c66affSColin Finck     for( i = X->n; i > 0; i-- )
854c2c66affSColin Finck         if( X->p[i - 1] != 0 )
855c2c66affSColin Finck             break;
856c2c66affSColin Finck 
857c2c66affSColin Finck     for( j = Y->n; j > 0; j-- )
858c2c66affSColin Finck         if( Y->p[j - 1] != 0 )
859c2c66affSColin Finck             break;
860c2c66affSColin Finck 
861c2c66affSColin Finck     if( i == 0 && j == 0 )
862c2c66affSColin Finck         return( 0 );
863c2c66affSColin Finck 
864c2c66affSColin Finck     if( i > j ) return(  X->s );
865c2c66affSColin Finck     if( j > i ) return( -Y->s );
866c2c66affSColin Finck 
867c2c66affSColin Finck     if( X->s > 0 && Y->s < 0 ) return(  1 );
868c2c66affSColin Finck     if( Y->s > 0 && X->s < 0 ) return( -1 );
869c2c66affSColin Finck 
870c2c66affSColin Finck     for( ; i > 0; i-- )
871c2c66affSColin Finck     {
872c2c66affSColin Finck         if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
873c2c66affSColin Finck         if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
874c2c66affSColin Finck     }
875c2c66affSColin Finck 
876c2c66affSColin Finck     return( 0 );
877c2c66affSColin Finck }
878c2c66affSColin Finck 
879c2c66affSColin Finck /*
880c2c66affSColin Finck  * Compare signed values
881c2c66affSColin Finck  */
882c2c66affSColin Finck int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
883c2c66affSColin Finck {
884c2c66affSColin Finck     mbedtls_mpi Y;
885c2c66affSColin Finck     mbedtls_mpi_uint p[1];
886c2c66affSColin Finck 
887c2c66affSColin Finck     *p  = ( z < 0 ) ? -z : z;
888c2c66affSColin Finck     Y.s = ( z < 0 ) ? -1 : 1;
889c2c66affSColin Finck     Y.n = 1;
890c2c66affSColin Finck     Y.p = p;
891c2c66affSColin Finck 
892c2c66affSColin Finck     return( mbedtls_mpi_cmp_mpi( X, &Y ) );
893c2c66affSColin Finck }
894c2c66affSColin Finck 
895c2c66affSColin Finck /*
896c2c66affSColin Finck  * Unsigned addition: X = |A| + |B|  (HAC 14.7)
897c2c66affSColin Finck  */
898c2c66affSColin Finck int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
899c2c66affSColin Finck {
900c2c66affSColin Finck     int ret;
901c2c66affSColin Finck     size_t i, j;
902c2c66affSColin Finck     mbedtls_mpi_uint *o, *p, c, tmp;
903c2c66affSColin Finck 
904c2c66affSColin Finck     if( X == B )
905c2c66affSColin Finck     {
906c2c66affSColin Finck         const mbedtls_mpi *T = A; A = X; B = T;
907c2c66affSColin Finck     }
908c2c66affSColin Finck 
909c2c66affSColin Finck     if( X != A )
910c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
911c2c66affSColin Finck 
912c2c66affSColin Finck     /*
913c2c66affSColin Finck      * X should always be positive as a result of unsigned additions.
914c2c66affSColin Finck      */
915c2c66affSColin Finck     X->s = 1;
916c2c66affSColin Finck 
917c2c66affSColin Finck     for( j = B->n; j > 0; j-- )
918c2c66affSColin Finck         if( B->p[j - 1] != 0 )
919c2c66affSColin Finck             break;
920c2c66affSColin Finck 
921c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
922c2c66affSColin Finck 
923c2c66affSColin Finck     o = B->p; p = X->p; c = 0;
924c2c66affSColin Finck 
925c2c66affSColin Finck     /*
926c2c66affSColin Finck      * tmp is used because it might happen that p == o
927c2c66affSColin Finck      */
928c2c66affSColin Finck     for( i = 0; i < j; i++, o++, p++ )
929c2c66affSColin Finck     {
930c2c66affSColin Finck         tmp= *o;
931c2c66affSColin Finck         *p +=  c; c  = ( *p <  c );
932c2c66affSColin Finck         *p += tmp; c += ( *p < tmp );
933c2c66affSColin Finck     }
934c2c66affSColin Finck 
935c2c66affSColin Finck     while( c != 0 )
936c2c66affSColin Finck     {
937c2c66affSColin Finck         if( i >= X->n )
938c2c66affSColin Finck         {
939c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
940c2c66affSColin Finck             p = X->p + i;
941c2c66affSColin Finck         }
942c2c66affSColin Finck 
943c2c66affSColin Finck         *p += c; c = ( *p < c ); i++; p++;
944c2c66affSColin Finck     }
945c2c66affSColin Finck 
946c2c66affSColin Finck cleanup:
947c2c66affSColin Finck 
948c2c66affSColin Finck     return( ret );
949c2c66affSColin Finck }
950c2c66affSColin Finck 
951c2c66affSColin Finck /*
952c2c66affSColin Finck  * Helper for mbedtls_mpi subtraction
953c2c66affSColin Finck  */
954c2c66affSColin Finck static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
955c2c66affSColin Finck {
956c2c66affSColin Finck     size_t i;
957c2c66affSColin Finck     mbedtls_mpi_uint c, z;
958c2c66affSColin Finck 
959c2c66affSColin Finck     for( i = c = 0; i < n; i++, s++, d++ )
960c2c66affSColin Finck     {
961c2c66affSColin Finck         z = ( *d <  c );     *d -=  c;
962c2c66affSColin Finck         c = ( *d < *s ) + z; *d -= *s;
963c2c66affSColin Finck     }
964c2c66affSColin Finck 
965c2c66affSColin Finck     while( c != 0 )
966c2c66affSColin Finck     {
967c2c66affSColin Finck         z = ( *d < c ); *d -= c;
968c2c66affSColin Finck         c = z; i++; d++;
969c2c66affSColin Finck     }
970c2c66affSColin Finck }
971c2c66affSColin Finck 
972c2c66affSColin Finck /*
973c2c66affSColin Finck  * Unsigned subtraction: X = |A| - |B|  (HAC 14.9)
974c2c66affSColin Finck  */
975c2c66affSColin Finck int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
976c2c66affSColin Finck {
977c2c66affSColin Finck     mbedtls_mpi TB;
978c2c66affSColin Finck     int ret;
979c2c66affSColin Finck     size_t n;
980c2c66affSColin Finck 
981c2c66affSColin Finck     if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
982c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
983c2c66affSColin Finck 
984c2c66affSColin Finck     mbedtls_mpi_init( &TB );
985c2c66affSColin Finck 
986c2c66affSColin Finck     if( X == B )
987c2c66affSColin Finck     {
988c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
989c2c66affSColin Finck         B = &TB;
990c2c66affSColin Finck     }
991c2c66affSColin Finck 
992c2c66affSColin Finck     if( X != A )
993c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
994c2c66affSColin Finck 
995c2c66affSColin Finck     /*
996c2c66affSColin Finck      * X should always be positive as a result of unsigned subtractions.
997c2c66affSColin Finck      */
998c2c66affSColin Finck     X->s = 1;
999c2c66affSColin Finck 
1000c2c66affSColin Finck     ret = 0;
1001c2c66affSColin Finck 
1002c2c66affSColin Finck     for( n = B->n; n > 0; n-- )
1003c2c66affSColin Finck         if( B->p[n - 1] != 0 )
1004c2c66affSColin Finck             break;
1005c2c66affSColin Finck 
1006c2c66affSColin Finck     mpi_sub_hlp( n, B->p, X->p );
1007c2c66affSColin Finck 
1008c2c66affSColin Finck cleanup:
1009c2c66affSColin Finck 
1010c2c66affSColin Finck     mbedtls_mpi_free( &TB );
1011c2c66affSColin Finck 
1012c2c66affSColin Finck     return( ret );
1013c2c66affSColin Finck }
1014c2c66affSColin Finck 
1015c2c66affSColin Finck /*
1016c2c66affSColin Finck  * Signed addition: X = A + B
1017c2c66affSColin Finck  */
1018c2c66affSColin Finck int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1019c2c66affSColin Finck {
1020c2c66affSColin Finck     int ret, s = A->s;
1021c2c66affSColin Finck 
1022c2c66affSColin Finck     if( A->s * B->s < 0 )
1023c2c66affSColin Finck     {
1024c2c66affSColin Finck         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1025c2c66affSColin Finck         {
1026c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1027c2c66affSColin Finck             X->s =  s;
1028c2c66affSColin Finck         }
1029c2c66affSColin Finck         else
1030c2c66affSColin Finck         {
1031c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1032c2c66affSColin Finck             X->s = -s;
1033c2c66affSColin Finck         }
1034c2c66affSColin Finck     }
1035c2c66affSColin Finck     else
1036c2c66affSColin Finck     {
1037c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1038c2c66affSColin Finck         X->s = s;
1039c2c66affSColin Finck     }
1040c2c66affSColin Finck 
1041c2c66affSColin Finck cleanup:
1042c2c66affSColin Finck 
1043c2c66affSColin Finck     return( ret );
1044c2c66affSColin Finck }
1045c2c66affSColin Finck 
1046c2c66affSColin Finck /*
1047c2c66affSColin Finck  * Signed subtraction: X = A - B
1048c2c66affSColin Finck  */
1049c2c66affSColin Finck int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1050c2c66affSColin Finck {
1051c2c66affSColin Finck     int ret, s = A->s;
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     if( A->s * B->s > 0 )
1054c2c66affSColin Finck     {
1055c2c66affSColin Finck         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1056c2c66affSColin Finck         {
1057c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1058c2c66affSColin Finck             X->s =  s;
1059c2c66affSColin Finck         }
1060c2c66affSColin Finck         else
1061c2c66affSColin Finck         {
1062c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1063c2c66affSColin Finck             X->s = -s;
1064c2c66affSColin Finck         }
1065c2c66affSColin Finck     }
1066c2c66affSColin Finck     else
1067c2c66affSColin Finck     {
1068c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1069c2c66affSColin Finck         X->s = s;
1070c2c66affSColin Finck     }
1071c2c66affSColin Finck 
1072c2c66affSColin Finck cleanup:
1073c2c66affSColin Finck 
1074c2c66affSColin Finck     return( ret );
1075c2c66affSColin Finck }
1076c2c66affSColin Finck 
1077c2c66affSColin Finck /*
1078c2c66affSColin Finck  * Signed addition: X = A + b
1079c2c66affSColin Finck  */
1080c2c66affSColin Finck int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1081c2c66affSColin Finck {
1082c2c66affSColin Finck     mbedtls_mpi _B;
1083c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1084c2c66affSColin Finck 
1085c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1086c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1087c2c66affSColin Finck     _B.n = 1;
1088c2c66affSColin Finck     _B.p = p;
1089c2c66affSColin Finck 
1090c2c66affSColin Finck     return( mbedtls_mpi_add_mpi( X, A, &_B ) );
1091c2c66affSColin Finck }
1092c2c66affSColin Finck 
1093c2c66affSColin Finck /*
1094c2c66affSColin Finck  * Signed subtraction: X = A - b
1095c2c66affSColin Finck  */
1096c2c66affSColin Finck int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1097c2c66affSColin Finck {
1098c2c66affSColin Finck     mbedtls_mpi _B;
1099c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1100c2c66affSColin Finck 
1101c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1102c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1103c2c66affSColin Finck     _B.n = 1;
1104c2c66affSColin Finck     _B.p = p;
1105c2c66affSColin Finck 
1106c2c66affSColin Finck     return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
1107c2c66affSColin Finck }
1108c2c66affSColin Finck 
1109c2c66affSColin Finck /*
1110c2c66affSColin Finck  * Helper for mbedtls_mpi multiplication
1111c2c66affSColin Finck  */
1112c2c66affSColin Finck static
1113c2c66affSColin Finck #if defined(__APPLE__) && defined(__arm__)
1114c2c66affSColin Finck /*
1115c2c66affSColin Finck  * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1116c2c66affSColin Finck  * appears to need this to prevent bad ARM code generation at -O3.
1117c2c66affSColin Finck  */
1118c2c66affSColin Finck __attribute__ ((noinline))
1119c2c66affSColin Finck #endif
1120c2c66affSColin Finck void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b )
1121c2c66affSColin Finck {
1122c2c66affSColin Finck     mbedtls_mpi_uint c = 0, t = 0;
1123c2c66affSColin Finck 
1124c2c66affSColin Finck #if defined(MULADDC_HUIT)
1125c2c66affSColin Finck     for( ; i >= 8; i -= 8 )
1126c2c66affSColin Finck     {
1127c2c66affSColin Finck         MULADDC_INIT
1128c2c66affSColin Finck         MULADDC_HUIT
1129c2c66affSColin Finck         MULADDC_STOP
1130c2c66affSColin Finck     }
1131c2c66affSColin Finck 
1132c2c66affSColin Finck     for( ; i > 0; i-- )
1133c2c66affSColin Finck     {
1134c2c66affSColin Finck         MULADDC_INIT
1135c2c66affSColin Finck         MULADDC_CORE
1136c2c66affSColin Finck         MULADDC_STOP
1137c2c66affSColin Finck     }
1138c2c66affSColin Finck #else /* MULADDC_HUIT */
1139c2c66affSColin Finck     for( ; i >= 16; i -= 16 )
1140c2c66affSColin Finck     {
1141c2c66affSColin Finck         MULADDC_INIT
1142c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1143c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1144c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1145c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1146c2c66affSColin Finck 
1147c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1148c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1149c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1150c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1151c2c66affSColin Finck         MULADDC_STOP
1152c2c66affSColin Finck     }
1153c2c66affSColin Finck 
1154c2c66affSColin Finck     for( ; i >= 8; i -= 8 )
1155c2c66affSColin Finck     {
1156c2c66affSColin Finck         MULADDC_INIT
1157c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1158c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1159c2c66affSColin Finck 
1160c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1161c2c66affSColin Finck         MULADDC_CORE   MULADDC_CORE
1162c2c66affSColin Finck         MULADDC_STOP
1163c2c66affSColin Finck     }
1164c2c66affSColin Finck 
1165c2c66affSColin Finck     for( ; i > 0; i-- )
1166c2c66affSColin Finck     {
1167c2c66affSColin Finck         MULADDC_INIT
1168c2c66affSColin Finck         MULADDC_CORE
1169c2c66affSColin Finck         MULADDC_STOP
1170c2c66affSColin Finck     }
1171c2c66affSColin Finck #endif /* MULADDC_HUIT */
1172c2c66affSColin Finck 
1173c2c66affSColin Finck     t++;
1174c2c66affSColin Finck 
1175c2c66affSColin Finck     do {
1176c2c66affSColin Finck         *d += c; c = ( *d < c ); d++;
1177c2c66affSColin Finck     }
1178c2c66affSColin Finck     while( c != 0 );
1179c2c66affSColin Finck }
1180c2c66affSColin Finck 
1181c2c66affSColin Finck /*
1182c2c66affSColin Finck  * Baseline multiplication: X = A * B  (HAC 14.12)
1183c2c66affSColin Finck  */
1184c2c66affSColin Finck int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1185c2c66affSColin Finck {
1186c2c66affSColin Finck     int ret;
1187c2c66affSColin Finck     size_t i, j;
1188c2c66affSColin Finck     mbedtls_mpi TA, TB;
1189c2c66affSColin Finck 
1190c2c66affSColin Finck     mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
1191c2c66affSColin Finck 
1192c2c66affSColin Finck     if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1193c2c66affSColin Finck     if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
1194c2c66affSColin Finck 
1195c2c66affSColin Finck     for( i = A->n; i > 0; i-- )
1196c2c66affSColin Finck         if( A->p[i - 1] != 0 )
1197c2c66affSColin Finck             break;
1198c2c66affSColin Finck 
1199c2c66affSColin Finck     for( j = B->n; j > 0; j-- )
1200c2c66affSColin Finck         if( B->p[j - 1] != 0 )
1201c2c66affSColin Finck             break;
1202c2c66affSColin Finck 
1203c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1204c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
1205c2c66affSColin Finck 
1206c2c66affSColin Finck     for( i++; j > 0; j-- )
1207c2c66affSColin Finck         mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] );
1208c2c66affSColin Finck 
1209c2c66affSColin Finck     X->s = A->s * B->s;
1210c2c66affSColin Finck 
1211c2c66affSColin Finck cleanup:
1212c2c66affSColin Finck 
1213c2c66affSColin Finck     mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
1214c2c66affSColin Finck 
1215c2c66affSColin Finck     return( ret );
1216c2c66affSColin Finck }
1217c2c66affSColin Finck 
1218c2c66affSColin Finck /*
1219c2c66affSColin Finck  * Baseline multiplication: X = A * b
1220c2c66affSColin Finck  */
1221c2c66affSColin Finck int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
1222c2c66affSColin Finck {
1223c2c66affSColin Finck     mbedtls_mpi _B;
1224c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1225c2c66affSColin Finck 
1226c2c66affSColin Finck     _B.s = 1;
1227c2c66affSColin Finck     _B.n = 1;
1228c2c66affSColin Finck     _B.p = p;
1229c2c66affSColin Finck     p[0] = b;
1230c2c66affSColin Finck 
1231c2c66affSColin Finck     return( mbedtls_mpi_mul_mpi( X, A, &_B ) );
1232c2c66affSColin Finck }
1233c2c66affSColin Finck 
1234c2c66affSColin Finck /*
1235c2c66affSColin Finck  * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1236c2c66affSColin Finck  * mbedtls_mpi_uint divisor, d
1237c2c66affSColin Finck  */
1238c2c66affSColin Finck static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1239c2c66affSColin Finck             mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
1240c2c66affSColin Finck {
1241c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL)
1242c2c66affSColin Finck     mbedtls_t_udbl dividend, quotient;
1243c2c66affSColin Finck #else
1244c2c66affSColin Finck     const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1245c2c66affSColin Finck     const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
1246c2c66affSColin Finck     mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1247c2c66affSColin Finck     mbedtls_mpi_uint u0_msw, u0_lsw;
1248c2c66affSColin Finck     size_t s;
1249c2c66affSColin Finck #endif
1250c2c66affSColin Finck 
1251c2c66affSColin Finck     /*
1252c2c66affSColin Finck      * Check for overflow
1253c2c66affSColin Finck      */
1254c2c66affSColin Finck     if( 0 == d || u1 >= d )
1255c2c66affSColin Finck     {
1256c2c66affSColin Finck         if (r != NULL) *r = ~0;
1257c2c66affSColin Finck 
1258c2c66affSColin Finck         return ( ~0 );
1259c2c66affSColin Finck     }
1260c2c66affSColin Finck 
1261c2c66affSColin Finck #if defined(MBEDTLS_HAVE_UDBL)
1262c2c66affSColin Finck     dividend  = (mbedtls_t_udbl) u1 << biL;
1263c2c66affSColin Finck     dividend |= (mbedtls_t_udbl) u0;
1264c2c66affSColin Finck     quotient = dividend / d;
1265c2c66affSColin Finck     if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1266c2c66affSColin Finck         quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1267c2c66affSColin Finck 
1268c2c66affSColin Finck     if( r != NULL )
1269c2c66affSColin Finck         *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
1270c2c66affSColin Finck 
1271c2c66affSColin Finck     return (mbedtls_mpi_uint) quotient;
1272c2c66affSColin Finck #else
1273c2c66affSColin Finck 
1274c2c66affSColin Finck     /*
1275c2c66affSColin Finck      * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1276c2c66affSColin Finck      *   Vol. 2 - Seminumerical Algorithms, Knuth
1277c2c66affSColin Finck      */
1278c2c66affSColin Finck 
1279c2c66affSColin Finck     /*
1280c2c66affSColin Finck      * Normalize the divisor, d, and dividend, u0, u1
1281c2c66affSColin Finck      */
1282c2c66affSColin Finck     s = mbedtls_clz( d );
1283c2c66affSColin Finck     d = d << s;
1284c2c66affSColin Finck 
1285c2c66affSColin Finck     u1 = u1 << s;
1286c2c66affSColin Finck     u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
1287c2c66affSColin Finck     u0 =  u0 << s;
1288c2c66affSColin Finck 
1289c2c66affSColin Finck     d1 = d >> biH;
1290c2c66affSColin Finck     d0 = d & uint_halfword_mask;
1291c2c66affSColin Finck 
1292c2c66affSColin Finck     u0_msw = u0 >> biH;
1293c2c66affSColin Finck     u0_lsw = u0 & uint_halfword_mask;
1294c2c66affSColin Finck 
1295c2c66affSColin Finck     /*
1296c2c66affSColin Finck      * Find the first quotient and remainder
1297c2c66affSColin Finck      */
1298c2c66affSColin Finck     q1 = u1 / d1;
1299c2c66affSColin Finck     r0 = u1 - d1 * q1;
1300c2c66affSColin Finck 
1301c2c66affSColin Finck     while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1302c2c66affSColin Finck     {
1303c2c66affSColin Finck         q1 -= 1;
1304c2c66affSColin Finck         r0 += d1;
1305c2c66affSColin Finck 
1306c2c66affSColin Finck         if ( r0 >= radix ) break;
1307c2c66affSColin Finck     }
1308c2c66affSColin Finck 
1309c2c66affSColin Finck     rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
1310c2c66affSColin Finck     q0 = rAX / d1;
1311c2c66affSColin Finck     r0 = rAX - q0 * d1;
1312c2c66affSColin Finck 
1313c2c66affSColin Finck     while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1314c2c66affSColin Finck     {
1315c2c66affSColin Finck         q0 -= 1;
1316c2c66affSColin Finck         r0 += d1;
1317c2c66affSColin Finck 
1318c2c66affSColin Finck         if ( r0 >= radix ) break;
1319c2c66affSColin Finck     }
1320c2c66affSColin Finck 
1321c2c66affSColin Finck     if (r != NULL)
1322c2c66affSColin Finck         *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
1323c2c66affSColin Finck 
1324c2c66affSColin Finck     quotient = q1 * radix + q0;
1325c2c66affSColin Finck 
1326c2c66affSColin Finck     return quotient;
1327c2c66affSColin Finck #endif
1328c2c66affSColin Finck }
1329c2c66affSColin Finck 
1330c2c66affSColin Finck /*
1331c2c66affSColin Finck  * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
1332c2c66affSColin Finck  */
1333c2c66affSColin Finck int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
1334c2c66affSColin Finck {
1335c2c66affSColin Finck     int ret;
1336c2c66affSColin Finck     size_t i, n, t, k;
1337c2c66affSColin Finck     mbedtls_mpi X, Y, Z, T1, T2;
1338c2c66affSColin Finck 
1339c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1340c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1341c2c66affSColin Finck 
1342c2c66affSColin Finck     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
1343c2c66affSColin Finck     mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
1344c2c66affSColin Finck 
1345c2c66affSColin Finck     if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1346c2c66affSColin Finck     {
1347c2c66affSColin Finck         if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1348c2c66affSColin Finck         if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
1349c2c66affSColin Finck         return( 0 );
1350c2c66affSColin Finck     }
1351c2c66affSColin Finck 
1352c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1353c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
1354c2c66affSColin Finck     X.s = Y.s = 1;
1355c2c66affSColin Finck 
1356c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1357c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z,  0 ) );
1358c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
1359c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
1360c2c66affSColin Finck 
1361c2c66affSColin Finck     k = mbedtls_mpi_bitlen( &Y ) % biL;
1362c2c66affSColin Finck     if( k < biL - 1 )
1363c2c66affSColin Finck     {
1364c2c66affSColin Finck         k = biL - 1 - k;
1365c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1366c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
1367c2c66affSColin Finck     }
1368c2c66affSColin Finck     else k = 0;
1369c2c66affSColin Finck 
1370c2c66affSColin Finck     n = X.n - 1;
1371c2c66affSColin Finck     t = Y.n - 1;
1372c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
1373c2c66affSColin Finck 
1374c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
1375c2c66affSColin Finck     {
1376c2c66affSColin Finck         Z.p[n - t]++;
1377c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
1378c2c66affSColin Finck     }
1379c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
1380c2c66affSColin Finck 
1381c2c66affSColin Finck     for( i = n; i > t ; i-- )
1382c2c66affSColin Finck     {
1383c2c66affSColin Finck         if( X.p[i] >= Y.p[t] )
1384c2c66affSColin Finck             Z.p[i - t - 1] = ~0;
1385c2c66affSColin Finck         else
1386c2c66affSColin Finck         {
1387c2c66affSColin Finck             Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1388c2c66affSColin Finck                                                             Y.p[t], NULL);
1389c2c66affSColin Finck         }
1390c2c66affSColin Finck 
1391c2c66affSColin Finck         Z.p[i - t - 1]++;
1392c2c66affSColin Finck         do
1393c2c66affSColin Finck         {
1394c2c66affSColin Finck             Z.p[i - t - 1]--;
1395c2c66affSColin Finck 
1396c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
1397c2c66affSColin Finck             T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
1398c2c66affSColin Finck             T1.p[1] = Y.p[t];
1399c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1400c2c66affSColin Finck 
1401c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
1402c2c66affSColin Finck             T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
1403c2c66affSColin Finck             T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
1404c2c66affSColin Finck             T2.p[2] = X.p[i];
1405c2c66affSColin Finck         }
1406c2c66affSColin Finck         while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
1407c2c66affSColin Finck 
1408c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1409c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1,  biL * ( i - t - 1 ) ) );
1410c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
1411c2c66affSColin Finck 
1412c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
1413c2c66affSColin Finck         {
1414c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1415c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1416c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
1417c2c66affSColin Finck             Z.p[i - t - 1]--;
1418c2c66affSColin Finck         }
1419c2c66affSColin Finck     }
1420c2c66affSColin Finck 
1421c2c66affSColin Finck     if( Q != NULL )
1422c2c66affSColin Finck     {
1423c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
1424c2c66affSColin Finck         Q->s = A->s * B->s;
1425c2c66affSColin Finck     }
1426c2c66affSColin Finck 
1427c2c66affSColin Finck     if( R != NULL )
1428c2c66affSColin Finck     {
1429c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
1430c2c66affSColin Finck         X.s = A->s;
1431c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
1432c2c66affSColin Finck 
1433c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
1434c2c66affSColin Finck             R->s = 1;
1435c2c66affSColin Finck     }
1436c2c66affSColin Finck 
1437c2c66affSColin Finck cleanup:
1438c2c66affSColin Finck 
1439c2c66affSColin Finck     mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
1440c2c66affSColin Finck     mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
1441c2c66affSColin Finck 
1442c2c66affSColin Finck     return( ret );
1443c2c66affSColin Finck }
1444c2c66affSColin Finck 
1445c2c66affSColin Finck /*
1446c2c66affSColin Finck  * Division by int: A = Q * b + R
1447c2c66affSColin Finck  */
1448c2c66affSColin Finck int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1449c2c66affSColin Finck {
1450c2c66affSColin Finck     mbedtls_mpi _B;
1451c2c66affSColin Finck     mbedtls_mpi_uint p[1];
1452c2c66affSColin Finck 
1453c2c66affSColin Finck     p[0] = ( b < 0 ) ? -b : b;
1454c2c66affSColin Finck     _B.s = ( b < 0 ) ? -1 : 1;
1455c2c66affSColin Finck     _B.n = 1;
1456c2c66affSColin Finck     _B.p = p;
1457c2c66affSColin Finck 
1458c2c66affSColin Finck     return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
1459c2c66affSColin Finck }
1460c2c66affSColin Finck 
1461c2c66affSColin Finck /*
1462c2c66affSColin Finck  * Modulo: R = A mod B
1463c2c66affSColin Finck  */
1464c2c66affSColin Finck int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
1465c2c66affSColin Finck {
1466c2c66affSColin Finck     int ret;
1467c2c66affSColin Finck 
1468c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1469c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1470c2c66affSColin Finck 
1471c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
1472c2c66affSColin Finck 
1473c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1474c2c66affSColin Finck       MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
1475c2c66affSColin Finck 
1476c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1477c2c66affSColin Finck       MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
1478c2c66affSColin Finck 
1479c2c66affSColin Finck cleanup:
1480c2c66affSColin Finck 
1481c2c66affSColin Finck     return( ret );
1482c2c66affSColin Finck }
1483c2c66affSColin Finck 
1484c2c66affSColin Finck /*
1485c2c66affSColin Finck  * Modulo: r = A mod b
1486c2c66affSColin Finck  */
1487c2c66affSColin Finck int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1488c2c66affSColin Finck {
1489c2c66affSColin Finck     size_t i;
1490c2c66affSColin Finck     mbedtls_mpi_uint x, y, z;
1491c2c66affSColin Finck 
1492c2c66affSColin Finck     if( b == 0 )
1493c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1494c2c66affSColin Finck 
1495c2c66affSColin Finck     if( b < 0 )
1496c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1497c2c66affSColin Finck 
1498c2c66affSColin Finck     /*
1499c2c66affSColin Finck      * handle trivial cases
1500c2c66affSColin Finck      */
1501c2c66affSColin Finck     if( b == 1 )
1502c2c66affSColin Finck     {
1503c2c66affSColin Finck         *r = 0;
1504c2c66affSColin Finck         return( 0 );
1505c2c66affSColin Finck     }
1506c2c66affSColin Finck 
1507c2c66affSColin Finck     if( b == 2 )
1508c2c66affSColin Finck     {
1509c2c66affSColin Finck         *r = A->p[0] & 1;
1510c2c66affSColin Finck         return( 0 );
1511c2c66affSColin Finck     }
1512c2c66affSColin Finck 
1513c2c66affSColin Finck     /*
1514c2c66affSColin Finck      * general case
1515c2c66affSColin Finck      */
1516c2c66affSColin Finck     for( i = A->n, y = 0; i > 0; i-- )
1517c2c66affSColin Finck     {
1518c2c66affSColin Finck         x  = A->p[i - 1];
1519c2c66affSColin Finck         y  = ( y << biH ) | ( x >> biH );
1520c2c66affSColin Finck         z  = y / b;
1521c2c66affSColin Finck         y -= z * b;
1522c2c66affSColin Finck 
1523c2c66affSColin Finck         x <<= biH;
1524c2c66affSColin Finck         y  = ( y << biH ) | ( x >> biH );
1525c2c66affSColin Finck         z  = y / b;
1526c2c66affSColin Finck         y -= z * b;
1527c2c66affSColin Finck     }
1528c2c66affSColin Finck 
1529c2c66affSColin Finck     /*
1530c2c66affSColin Finck      * If A is negative, then the current y represents a negative value.
1531c2c66affSColin Finck      * Flipping it to the positive side.
1532c2c66affSColin Finck      */
1533c2c66affSColin Finck     if( A->s < 0 && y != 0 )
1534c2c66affSColin Finck         y = b - y;
1535c2c66affSColin Finck 
1536c2c66affSColin Finck     *r = y;
1537c2c66affSColin Finck 
1538c2c66affSColin Finck     return( 0 );
1539c2c66affSColin Finck }
1540c2c66affSColin Finck 
1541c2c66affSColin Finck /*
1542c2c66affSColin Finck  * Fast Montgomery initialization (thanks to Tom St Denis)
1543c2c66affSColin Finck  */
1544c2c66affSColin Finck static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
1545c2c66affSColin Finck {
1546c2c66affSColin Finck     mbedtls_mpi_uint x, m0 = N->p[0];
1547c2c66affSColin Finck     unsigned int i;
1548c2c66affSColin Finck 
1549c2c66affSColin Finck     x  = m0;
1550c2c66affSColin Finck     x += ( ( m0 + 2 ) & 4 ) << 1;
1551c2c66affSColin Finck 
1552c2c66affSColin Finck     for( i = biL; i >= 8; i /= 2 )
1553c2c66affSColin Finck         x *= ( 2 - ( m0 * x ) );
1554c2c66affSColin Finck 
1555c2c66affSColin Finck     *mm = ~x + 1;
1556c2c66affSColin Finck }
1557c2c66affSColin Finck 
1558c2c66affSColin Finck /*
1559c2c66affSColin Finck  * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
1560c2c66affSColin Finck  */
1561c2c66affSColin Finck static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1562c2c66affSColin Finck                          const mbedtls_mpi *T )
1563c2c66affSColin Finck {
1564c2c66affSColin Finck     size_t i, n, m;
1565c2c66affSColin Finck     mbedtls_mpi_uint u0, u1, *d;
1566c2c66affSColin Finck 
1567c2c66affSColin Finck     if( T->n < N->n + 1 || T->p == NULL )
1568c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1569c2c66affSColin Finck 
1570c2c66affSColin Finck     memset( T->p, 0, T->n * ciL );
1571c2c66affSColin Finck 
1572c2c66affSColin Finck     d = T->p;
1573c2c66affSColin Finck     n = N->n;
1574c2c66affSColin Finck     m = ( B->n < n ) ? B->n : n;
1575c2c66affSColin Finck 
1576c2c66affSColin Finck     for( i = 0; i < n; i++ )
1577c2c66affSColin Finck     {
1578c2c66affSColin Finck         /*
1579c2c66affSColin Finck          * T = (T + u0*B + u1*N) / 2^biL
1580c2c66affSColin Finck          */
1581c2c66affSColin Finck         u0 = A->p[i];
1582c2c66affSColin Finck         u1 = ( d[0] + u0 * B->p[0] ) * mm;
1583c2c66affSColin Finck 
1584c2c66affSColin Finck         mpi_mul_hlp( m, B->p, d, u0 );
1585c2c66affSColin Finck         mpi_mul_hlp( n, N->p, d, u1 );
1586c2c66affSColin Finck 
1587c2c66affSColin Finck         *d++ = u0; d[n + 1] = 0;
1588c2c66affSColin Finck     }
1589c2c66affSColin Finck 
1590c2c66affSColin Finck     memcpy( A->p, d, ( n + 1 ) * ciL );
1591c2c66affSColin Finck 
1592c2c66affSColin Finck     if( mbedtls_mpi_cmp_abs( A, N ) >= 0 )
1593c2c66affSColin Finck         mpi_sub_hlp( n, N->p, A->p );
1594c2c66affSColin Finck     else
1595c2c66affSColin Finck         /* prevent timing attacks */
1596c2c66affSColin Finck         mpi_sub_hlp( n, A->p, T->p );
1597c2c66affSColin Finck 
1598c2c66affSColin Finck     return( 0 );
1599c2c66affSColin Finck }
1600c2c66affSColin Finck 
1601c2c66affSColin Finck /*
1602c2c66affSColin Finck  * Montgomery reduction: A = A * R^-1 mod N
1603c2c66affSColin Finck  */
1604c2c66affSColin Finck static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T )
1605c2c66affSColin Finck {
1606c2c66affSColin Finck     mbedtls_mpi_uint z = 1;
1607c2c66affSColin Finck     mbedtls_mpi U;
1608c2c66affSColin Finck 
1609c2c66affSColin Finck     U.n = U.s = (int) z;
1610c2c66affSColin Finck     U.p = &z;
1611c2c66affSColin Finck 
1612c2c66affSColin Finck     return( mpi_montmul( A, &U, N, mm, T ) );
1613c2c66affSColin Finck }
1614c2c66affSColin Finck 
1615c2c66affSColin Finck /*
1616c2c66affSColin Finck  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
1617c2c66affSColin Finck  */
1618c2c66affSColin Finck int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR )
1619c2c66affSColin Finck {
1620c2c66affSColin Finck     int ret;
1621c2c66affSColin Finck     size_t wbits, wsize, one = 1;
1622c2c66affSColin Finck     size_t i, j, nblimbs;
1623c2c66affSColin Finck     size_t bufsize, nbits;
1624c2c66affSColin Finck     mbedtls_mpi_uint ei, mm, state;
1625c2c66affSColin Finck     mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
1626c2c66affSColin Finck     int neg;
1627c2c66affSColin Finck 
1628*d9e6c9b5SThomas Faber     if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
1629c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1630c2c66affSColin Finck 
1631c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
1632c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1633c2c66affSColin Finck 
1634c2c66affSColin Finck     /*
1635c2c66affSColin Finck      * Init temps and window size
1636c2c66affSColin Finck      */
1637c2c66affSColin Finck     mpi_montg_init( &mm, N );
1638c2c66affSColin Finck     mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T );
1639c2c66affSColin Finck     mbedtls_mpi_init( &Apos );
1640c2c66affSColin Finck     memset( W, 0, sizeof( W ) );
1641c2c66affSColin Finck 
1642c2c66affSColin Finck     i = mbedtls_mpi_bitlen( E );
1643c2c66affSColin Finck 
1644c2c66affSColin Finck     wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1645c2c66affSColin Finck             ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
1646c2c66affSColin Finck 
1647c2c66affSColin Finck     if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
1648c2c66affSColin Finck         wsize = MBEDTLS_MPI_WINDOW_SIZE;
1649c2c66affSColin Finck 
1650c2c66affSColin Finck     j = N->n + 1;
1651c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1652c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1],  j ) );
1653c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
1654c2c66affSColin Finck 
1655c2c66affSColin Finck     /*
1656c2c66affSColin Finck      * Compensate for negative A (and correct at the end)
1657c2c66affSColin Finck      */
1658c2c66affSColin Finck     neg = ( A->s == -1 );
1659c2c66affSColin Finck     if( neg )
1660c2c66affSColin Finck     {
1661c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
1662c2c66affSColin Finck         Apos.s = 1;
1663c2c66affSColin Finck         A = &Apos;
1664c2c66affSColin Finck     }
1665c2c66affSColin Finck 
1666c2c66affSColin Finck     /*
1667c2c66affSColin Finck      * If 1st call, pre-compute R^2 mod N
1668c2c66affSColin Finck      */
1669c2c66affSColin Finck     if( _RR == NULL || _RR->p == NULL )
1670c2c66affSColin Finck     {
1671c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
1672c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
1673c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
1674c2c66affSColin Finck 
1675c2c66affSColin Finck         if( _RR != NULL )
1676c2c66affSColin Finck             memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
1677c2c66affSColin Finck     }
1678c2c66affSColin Finck     else
1679c2c66affSColin Finck         memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
1680c2c66affSColin Finck 
1681c2c66affSColin Finck     /*
1682c2c66affSColin Finck      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1683c2c66affSColin Finck      */
1684c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
1685c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
1686c2c66affSColin Finck     else
1687c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
1688c2c66affSColin Finck 
1689c2c66affSColin Finck     MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) );
1690c2c66affSColin Finck 
1691c2c66affSColin Finck     /*
1692c2c66affSColin Finck      * X = R^2 * R^-1 mod N = R mod N
1693c2c66affSColin Finck      */
1694c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
1695c2c66affSColin Finck     MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
1696c2c66affSColin Finck 
1697c2c66affSColin Finck     if( wsize > 1 )
1698c2c66affSColin Finck     {
1699c2c66affSColin Finck         /*
1700c2c66affSColin Finck          * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1701c2c66affSColin Finck          */
1702c2c66affSColin Finck         j =  one << ( wsize - 1 );
1703c2c66affSColin Finck 
1704c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
1705c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1]    ) );
1706c2c66affSColin Finck 
1707c2c66affSColin Finck         for( i = 0; i < wsize - 1; i++ )
1708c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) );
1709c2c66affSColin Finck 
1710c2c66affSColin Finck         /*
1711c2c66affSColin Finck          * W[i] = W[i - 1] * W[1]
1712c2c66affSColin Finck          */
1713c2c66affSColin Finck         for( i = j + 1; i < ( one << wsize ); i++ )
1714c2c66affSColin Finck         {
1715c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
1716c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
1717c2c66affSColin Finck 
1718c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) );
1719c2c66affSColin Finck         }
1720c2c66affSColin Finck     }
1721c2c66affSColin Finck 
1722c2c66affSColin Finck     nblimbs = E->n;
1723c2c66affSColin Finck     bufsize = 0;
1724c2c66affSColin Finck     nbits   = 0;
1725c2c66affSColin Finck     wbits   = 0;
1726c2c66affSColin Finck     state   = 0;
1727c2c66affSColin Finck 
1728c2c66affSColin Finck     while( 1 )
1729c2c66affSColin Finck     {
1730c2c66affSColin Finck         if( bufsize == 0 )
1731c2c66affSColin Finck         {
1732c2c66affSColin Finck             if( nblimbs == 0 )
1733c2c66affSColin Finck                 break;
1734c2c66affSColin Finck 
1735c2c66affSColin Finck             nblimbs--;
1736c2c66affSColin Finck 
1737c2c66affSColin Finck             bufsize = sizeof( mbedtls_mpi_uint ) << 3;
1738c2c66affSColin Finck         }
1739c2c66affSColin Finck 
1740c2c66affSColin Finck         bufsize--;
1741c2c66affSColin Finck 
1742c2c66affSColin Finck         ei = (E->p[nblimbs] >> bufsize) & 1;
1743c2c66affSColin Finck 
1744c2c66affSColin Finck         /*
1745c2c66affSColin Finck          * skip leading 0s
1746c2c66affSColin Finck          */
1747c2c66affSColin Finck         if( ei == 0 && state == 0 )
1748c2c66affSColin Finck             continue;
1749c2c66affSColin Finck 
1750c2c66affSColin Finck         if( ei == 0 && state == 1 )
1751c2c66affSColin Finck         {
1752c2c66affSColin Finck             /*
1753c2c66affSColin Finck              * out of window, square X
1754c2c66affSColin Finck              */
1755c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
1756c2c66affSColin Finck             continue;
1757c2c66affSColin Finck         }
1758c2c66affSColin Finck 
1759c2c66affSColin Finck         /*
1760c2c66affSColin Finck          * add ei to current window
1761c2c66affSColin Finck          */
1762c2c66affSColin Finck         state = 2;
1763c2c66affSColin Finck 
1764c2c66affSColin Finck         nbits++;
1765c2c66affSColin Finck         wbits |= ( ei << ( wsize - nbits ) );
1766c2c66affSColin Finck 
1767c2c66affSColin Finck         if( nbits == wsize )
1768c2c66affSColin Finck         {
1769c2c66affSColin Finck             /*
1770c2c66affSColin Finck              * X = X^wsize R^-1 mod N
1771c2c66affSColin Finck              */
1772c2c66affSColin Finck             for( i = 0; i < wsize; i++ )
1773c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
1774c2c66affSColin Finck 
1775c2c66affSColin Finck             /*
1776c2c66affSColin Finck              * X = X * W[wbits] R^-1 mod N
1777c2c66affSColin Finck              */
1778c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) );
1779c2c66affSColin Finck 
1780c2c66affSColin Finck             state--;
1781c2c66affSColin Finck             nbits = 0;
1782c2c66affSColin Finck             wbits = 0;
1783c2c66affSColin Finck         }
1784c2c66affSColin Finck     }
1785c2c66affSColin Finck 
1786c2c66affSColin Finck     /*
1787c2c66affSColin Finck      * process the remaining bits
1788c2c66affSColin Finck      */
1789c2c66affSColin Finck     for( i = 0; i < nbits; i++ )
1790c2c66affSColin Finck     {
1791c2c66affSColin Finck         MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) );
1792c2c66affSColin Finck 
1793c2c66affSColin Finck         wbits <<= 1;
1794c2c66affSColin Finck 
1795c2c66affSColin Finck         if( ( wbits & ( one << wsize ) ) != 0 )
1796c2c66affSColin Finck             MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) );
1797c2c66affSColin Finck     }
1798c2c66affSColin Finck 
1799c2c66affSColin Finck     /*
1800c2c66affSColin Finck      * X = A^E * R * R^-1 mod N = A^E mod N
1801c2c66affSColin Finck      */
1802c2c66affSColin Finck     MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) );
1803c2c66affSColin Finck 
1804c2c66affSColin Finck     if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
1805c2c66affSColin Finck     {
1806c2c66affSColin Finck         X->s = -1;
1807c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
1808c2c66affSColin Finck     }
1809c2c66affSColin Finck 
1810c2c66affSColin Finck cleanup:
1811c2c66affSColin Finck 
1812c2c66affSColin Finck     for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ )
1813c2c66affSColin Finck         mbedtls_mpi_free( &W[i] );
1814c2c66affSColin Finck 
1815c2c66affSColin Finck     mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
1816c2c66affSColin Finck 
1817c2c66affSColin Finck     if( _RR == NULL || _RR->p == NULL )
1818c2c66affSColin Finck         mbedtls_mpi_free( &RR );
1819c2c66affSColin Finck 
1820c2c66affSColin Finck     return( ret );
1821c2c66affSColin Finck }
1822c2c66affSColin Finck 
1823c2c66affSColin Finck /*
1824c2c66affSColin Finck  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
1825c2c66affSColin Finck  */
1826c2c66affSColin Finck int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
1827c2c66affSColin Finck {
1828c2c66affSColin Finck     int ret;
1829c2c66affSColin Finck     size_t lz, lzt;
1830c2c66affSColin Finck     mbedtls_mpi TG, TA, TB;
1831c2c66affSColin Finck 
1832c2c66affSColin Finck     mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB );
1833c2c66affSColin Finck 
1834c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
1835c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
1836c2c66affSColin Finck 
1837c2c66affSColin Finck     lz = mbedtls_mpi_lsb( &TA );
1838c2c66affSColin Finck     lzt = mbedtls_mpi_lsb( &TB );
1839c2c66affSColin Finck 
1840c2c66affSColin Finck     if( lzt < lz )
1841c2c66affSColin Finck         lz = lzt;
1842c2c66affSColin Finck 
1843c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) );
1844c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) );
1845c2c66affSColin Finck 
1846c2c66affSColin Finck     TA.s = TB.s = 1;
1847c2c66affSColin Finck 
1848c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
1849c2c66affSColin Finck     {
1850c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
1851c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
1852c2c66affSColin Finck 
1853c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
1854c2c66affSColin Finck         {
1855c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
1856c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
1857c2c66affSColin Finck         }
1858c2c66affSColin Finck         else
1859c2c66affSColin Finck         {
1860c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
1861c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
1862c2c66affSColin Finck         }
1863c2c66affSColin Finck     }
1864c2c66affSColin Finck 
1865c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
1866c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
1867c2c66affSColin Finck 
1868c2c66affSColin Finck cleanup:
1869c2c66affSColin Finck 
1870c2c66affSColin Finck     mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
1871c2c66affSColin Finck 
1872c2c66affSColin Finck     return( ret );
1873c2c66affSColin Finck }
1874c2c66affSColin Finck 
1875c2c66affSColin Finck /*
1876c2c66affSColin Finck  * Fill X with size bytes of random.
1877c2c66affSColin Finck  *
1878c2c66affSColin Finck  * Use a temporary bytes representation to make sure the result is the same
1879c2c66affSColin Finck  * regardless of the platform endianness (useful when f_rng is actually
1880c2c66affSColin Finck  * deterministic, eg for tests).
1881c2c66affSColin Finck  */
1882c2c66affSColin Finck int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
1883c2c66affSColin Finck                      int (*f_rng)(void *, unsigned char *, size_t),
1884c2c66affSColin Finck                      void *p_rng )
1885c2c66affSColin Finck {
1886c2c66affSColin Finck     int ret;
1887c2c66affSColin Finck     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
1888c2c66affSColin Finck 
1889c2c66affSColin Finck     if( size > MBEDTLS_MPI_MAX_SIZE )
1890c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1891c2c66affSColin Finck 
1892c2c66affSColin Finck     MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) );
1893c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) );
1894c2c66affSColin Finck 
1895c2c66affSColin Finck cleanup:
1896*d9e6c9b5SThomas Faber     mbedtls_zeroize( buf, sizeof( buf ) );
1897c2c66affSColin Finck     return( ret );
1898c2c66affSColin Finck }
1899c2c66affSColin Finck 
1900c2c66affSColin Finck /*
1901c2c66affSColin Finck  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
1902c2c66affSColin Finck  */
1903c2c66affSColin Finck int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
1904c2c66affSColin Finck {
1905c2c66affSColin Finck     int ret;
1906c2c66affSColin Finck     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1907c2c66affSColin Finck 
1908c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
1909c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
1910c2c66affSColin Finck 
1911c2c66affSColin Finck     mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 );
1912c2c66affSColin Finck     mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV );
1913c2c66affSColin Finck     mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 );
1914c2c66affSColin Finck 
1915c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
1916c2c66affSColin Finck 
1917c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
1918c2c66affSColin Finck     {
1919c2c66affSColin Finck         ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
1920c2c66affSColin Finck         goto cleanup;
1921c2c66affSColin Finck     }
1922c2c66affSColin Finck 
1923c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
1924c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
1925c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
1926c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
1927c2c66affSColin Finck 
1928c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
1929c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
1930c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
1931c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
1932c2c66affSColin Finck 
1933c2c66affSColin Finck     do
1934c2c66affSColin Finck     {
1935c2c66affSColin Finck         while( ( TU.p[0] & 1 ) == 0 )
1936c2c66affSColin Finck         {
1937c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
1938c2c66affSColin Finck 
1939c2c66affSColin Finck             if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1940c2c66affSColin Finck             {
1941c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
1942c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
1943c2c66affSColin Finck             }
1944c2c66affSColin Finck 
1945c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
1946c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
1947c2c66affSColin Finck         }
1948c2c66affSColin Finck 
1949c2c66affSColin Finck         while( ( TV.p[0] & 1 ) == 0 )
1950c2c66affSColin Finck         {
1951c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
1952c2c66affSColin Finck 
1953c2c66affSColin Finck             if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1954c2c66affSColin Finck             {
1955c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
1956c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
1957c2c66affSColin Finck             }
1958c2c66affSColin Finck 
1959c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
1960c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
1961c2c66affSColin Finck         }
1962c2c66affSColin Finck 
1963c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
1964c2c66affSColin Finck         {
1965c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
1966c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
1967c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
1968c2c66affSColin Finck         }
1969c2c66affSColin Finck         else
1970c2c66affSColin Finck         {
1971c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
1972c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
1973c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
1974c2c66affSColin Finck         }
1975c2c66affSColin Finck     }
1976c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
1977c2c66affSColin Finck 
1978c2c66affSColin Finck     while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
1979c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
1980c2c66affSColin Finck 
1981c2c66affSColin Finck     while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
1982c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
1983c2c66affSColin Finck 
1984c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
1985c2c66affSColin Finck 
1986c2c66affSColin Finck cleanup:
1987c2c66affSColin Finck 
1988c2c66affSColin Finck     mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
1989c2c66affSColin Finck     mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
1990c2c66affSColin Finck     mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
1991c2c66affSColin Finck 
1992c2c66affSColin Finck     return( ret );
1993c2c66affSColin Finck }
1994c2c66affSColin Finck 
1995c2c66affSColin Finck #if defined(MBEDTLS_GENPRIME)
1996c2c66affSColin Finck 
1997c2c66affSColin Finck static const int small_prime[] =
1998c2c66affSColin Finck {
1999c2c66affSColin Finck         3,    5,    7,   11,   13,   17,   19,   23,
2000c2c66affSColin Finck        29,   31,   37,   41,   43,   47,   53,   59,
2001c2c66affSColin Finck        61,   67,   71,   73,   79,   83,   89,   97,
2002c2c66affSColin Finck       101,  103,  107,  109,  113,  127,  131,  137,
2003c2c66affSColin Finck       139,  149,  151,  157,  163,  167,  173,  179,
2004c2c66affSColin Finck       181,  191,  193,  197,  199,  211,  223,  227,
2005c2c66affSColin Finck       229,  233,  239,  241,  251,  257,  263,  269,
2006c2c66affSColin Finck       271,  277,  281,  283,  293,  307,  311,  313,
2007c2c66affSColin Finck       317,  331,  337,  347,  349,  353,  359,  367,
2008c2c66affSColin Finck       373,  379,  383,  389,  397,  401,  409,  419,
2009c2c66affSColin Finck       421,  431,  433,  439,  443,  449,  457,  461,
2010c2c66affSColin Finck       463,  467,  479,  487,  491,  499,  503,  509,
2011c2c66affSColin Finck       521,  523,  541,  547,  557,  563,  569,  571,
2012c2c66affSColin Finck       577,  587,  593,  599,  601,  607,  613,  617,
2013c2c66affSColin Finck       619,  631,  641,  643,  647,  653,  659,  661,
2014c2c66affSColin Finck       673,  677,  683,  691,  701,  709,  719,  727,
2015c2c66affSColin Finck       733,  739,  743,  751,  757,  761,  769,  773,
2016c2c66affSColin Finck       787,  797,  809,  811,  821,  823,  827,  829,
2017c2c66affSColin Finck       839,  853,  857,  859,  863,  877,  881,  883,
2018c2c66affSColin Finck       887,  907,  911,  919,  929,  937,  941,  947,
2019c2c66affSColin Finck       953,  967,  971,  977,  983,  991,  997, -103
2020c2c66affSColin Finck };
2021c2c66affSColin Finck 
2022c2c66affSColin Finck /*
2023c2c66affSColin Finck  * Small divisors test (X must be positive)
2024c2c66affSColin Finck  *
2025c2c66affSColin Finck  * Return values:
2026c2c66affSColin Finck  * 0: no small factor (possible prime, more tests needed)
2027c2c66affSColin Finck  * 1: certain prime
2028c2c66affSColin Finck  * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2029c2c66affSColin Finck  * other negative: error
2030c2c66affSColin Finck  */
2031c2c66affSColin Finck static int mpi_check_small_factors( const mbedtls_mpi *X )
2032c2c66affSColin Finck {
2033c2c66affSColin Finck     int ret = 0;
2034c2c66affSColin Finck     size_t i;
2035c2c66affSColin Finck     mbedtls_mpi_uint r;
2036c2c66affSColin Finck 
2037c2c66affSColin Finck     if( ( X->p[0] & 1 ) == 0 )
2038c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2039c2c66affSColin Finck 
2040c2c66affSColin Finck     for( i = 0; small_prime[i] > 0; i++ )
2041c2c66affSColin Finck     {
2042c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
2043c2c66affSColin Finck             return( 1 );
2044c2c66affSColin Finck 
2045c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
2046c2c66affSColin Finck 
2047c2c66affSColin Finck         if( r == 0 )
2048c2c66affSColin Finck             return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2049c2c66affSColin Finck     }
2050c2c66affSColin Finck 
2051c2c66affSColin Finck cleanup:
2052c2c66affSColin Finck     return( ret );
2053c2c66affSColin Finck }
2054c2c66affSColin Finck 
2055c2c66affSColin Finck /*
2056c2c66affSColin Finck  * Miller-Rabin pseudo-primality test  (HAC 4.24)
2057c2c66affSColin Finck  */
2058c2c66affSColin Finck static int mpi_miller_rabin( const mbedtls_mpi *X,
2059c2c66affSColin Finck                              int (*f_rng)(void *, unsigned char *, size_t),
2060c2c66affSColin Finck                              void *p_rng )
2061c2c66affSColin Finck {
2062c2c66affSColin Finck     int ret, count;
2063c2c66affSColin Finck     size_t i, j, k, n, s;
2064c2c66affSColin Finck     mbedtls_mpi W, R, T, A, RR;
2065c2c66affSColin Finck 
2066c2c66affSColin Finck     mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
2067c2c66affSColin Finck     mbedtls_mpi_init( &RR );
2068c2c66affSColin Finck 
2069c2c66affSColin Finck     /*
2070c2c66affSColin Finck      * W = |X| - 1
2071c2c66affSColin Finck      * R = W >> lsb( W )
2072c2c66affSColin Finck      */
2073c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2074c2c66affSColin Finck     s = mbedtls_mpi_lsb( &W );
2075c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2076c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
2077c2c66affSColin Finck 
2078c2c66affSColin Finck     i = mbedtls_mpi_bitlen( X );
2079c2c66affSColin Finck     /*
2080c2c66affSColin Finck      * HAC, table 4.4
2081c2c66affSColin Finck      */
2082c2c66affSColin Finck     n = ( ( i >= 1300 ) ?  2 : ( i >=  850 ) ?  3 :
2083c2c66affSColin Finck           ( i >=  650 ) ?  4 : ( i >=  350 ) ?  8 :
2084c2c66affSColin Finck           ( i >=  250 ) ? 12 : ( i >=  150 ) ? 18 : 27 );
2085c2c66affSColin Finck 
2086c2c66affSColin Finck     for( i = 0; i < n; i++ )
2087c2c66affSColin Finck     {
2088c2c66affSColin Finck         /*
2089c2c66affSColin Finck          * pick a random A, 1 < A < |X| - 1
2090c2c66affSColin Finck          */
2091c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2092c2c66affSColin Finck 
2093c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
2094c2c66affSColin Finck         {
2095c2c66affSColin Finck             j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
2096c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
2097c2c66affSColin Finck         }
2098c2c66affSColin Finck         A.p[0] |= 3;
2099c2c66affSColin Finck 
2100c2c66affSColin Finck         count = 0;
2101c2c66affSColin Finck         do {
2102c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2103c2c66affSColin Finck 
2104c2c66affSColin Finck             j = mbedtls_mpi_bitlen( &A );
2105c2c66affSColin Finck             k = mbedtls_mpi_bitlen( &W );
2106c2c66affSColin Finck             if (j > k) {
2107c2c66affSColin Finck                 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) );
2108c2c66affSColin Finck             }
2109c2c66affSColin Finck 
2110c2c66affSColin Finck             if (count++ > 30) {
2111c2c66affSColin Finck                 return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2112c2c66affSColin Finck             }
2113c2c66affSColin Finck 
2114c2c66affSColin Finck         } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2115c2c66affSColin Finck                   mbedtls_mpi_cmp_int( &A, 1 )  <= 0    );
2116c2c66affSColin Finck 
2117c2c66affSColin Finck         /*
2118c2c66affSColin Finck          * A = A^R mod |X|
2119c2c66affSColin Finck          */
2120c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
2121c2c66affSColin Finck 
2122c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2123c2c66affSColin Finck             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
2124c2c66affSColin Finck             continue;
2125c2c66affSColin Finck 
2126c2c66affSColin Finck         j = 1;
2127c2c66affSColin Finck         while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
2128c2c66affSColin Finck         {
2129c2c66affSColin Finck             /*
2130c2c66affSColin Finck              * A = A * A mod |X|
2131c2c66affSColin Finck              */
2132c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2133c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X  ) );
2134c2c66affSColin Finck 
2135c2c66affSColin Finck             if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
2136c2c66affSColin Finck                 break;
2137c2c66affSColin Finck 
2138c2c66affSColin Finck             j++;
2139c2c66affSColin Finck         }
2140c2c66affSColin Finck 
2141c2c66affSColin Finck         /*
2142c2c66affSColin Finck          * not prime if A != |X| - 1 or A == 1
2143c2c66affSColin Finck          */
2144c2c66affSColin Finck         if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2145c2c66affSColin Finck             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
2146c2c66affSColin Finck         {
2147c2c66affSColin Finck             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2148c2c66affSColin Finck             break;
2149c2c66affSColin Finck         }
2150c2c66affSColin Finck     }
2151c2c66affSColin Finck 
2152c2c66affSColin Finck cleanup:
2153c2c66affSColin Finck     mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2154c2c66affSColin Finck     mbedtls_mpi_free( &RR );
2155c2c66affSColin Finck 
2156c2c66affSColin Finck     return( ret );
2157c2c66affSColin Finck }
2158c2c66affSColin Finck 
2159c2c66affSColin Finck /*
2160c2c66affSColin Finck  * Pseudo-primality test: small factors, then Miller-Rabin
2161c2c66affSColin Finck  */
2162c2c66affSColin Finck int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2163c2c66affSColin Finck                   int (*f_rng)(void *, unsigned char *, size_t),
2164c2c66affSColin Finck                   void *p_rng )
2165c2c66affSColin Finck {
2166c2c66affSColin Finck     int ret;
2167c2c66affSColin Finck     mbedtls_mpi XX;
2168c2c66affSColin Finck 
2169c2c66affSColin Finck     XX.s = 1;
2170c2c66affSColin Finck     XX.n = X->n;
2171c2c66affSColin Finck     XX.p = X->p;
2172c2c66affSColin Finck 
2173c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2174c2c66affSColin Finck         mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2175c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2176c2c66affSColin Finck 
2177c2c66affSColin Finck     if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
2178c2c66affSColin Finck         return( 0 );
2179c2c66affSColin Finck 
2180c2c66affSColin Finck     if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2181c2c66affSColin Finck     {
2182c2c66affSColin Finck         if( ret == 1 )
2183c2c66affSColin Finck             return( 0 );
2184c2c66affSColin Finck 
2185c2c66affSColin Finck         return( ret );
2186c2c66affSColin Finck     }
2187c2c66affSColin Finck 
2188c2c66affSColin Finck     return( mpi_miller_rabin( &XX, f_rng, p_rng ) );
2189c2c66affSColin Finck }
2190c2c66affSColin Finck 
2191c2c66affSColin Finck /*
2192c2c66affSColin Finck  * Prime number generation
2193c2c66affSColin Finck  */
2194c2c66affSColin Finck int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
2195c2c66affSColin Finck                    int (*f_rng)(void *, unsigned char *, size_t),
2196c2c66affSColin Finck                    void *p_rng )
2197c2c66affSColin Finck {
2198c2c66affSColin Finck     int ret;
2199c2c66affSColin Finck     size_t k, n;
2200c2c66affSColin Finck     mbedtls_mpi_uint r;
2201c2c66affSColin Finck     mbedtls_mpi Y;
2202c2c66affSColin Finck 
2203c2c66affSColin Finck     if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2204c2c66affSColin Finck         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2205c2c66affSColin Finck 
2206c2c66affSColin Finck     mbedtls_mpi_init( &Y );
2207c2c66affSColin Finck 
2208c2c66affSColin Finck     n = BITS_TO_LIMBS( nbits );
2209c2c66affSColin Finck 
2210c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
2211c2c66affSColin Finck 
2212c2c66affSColin Finck     k = mbedtls_mpi_bitlen( X );
2213c2c66affSColin Finck     if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) );
2214c2c66affSColin Finck 
2215c2c66affSColin Finck     mbedtls_mpi_set_bit( X, nbits-1, 1 );
2216c2c66affSColin Finck 
2217c2c66affSColin Finck     X->p[0] |= 1;
2218c2c66affSColin Finck 
2219c2c66affSColin Finck     if( dh_flag == 0 )
2220c2c66affSColin Finck     {
2221c2c66affSColin Finck         while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
2222c2c66affSColin Finck         {
2223c2c66affSColin Finck             if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2224c2c66affSColin Finck                 goto cleanup;
2225c2c66affSColin Finck 
2226c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) );
2227c2c66affSColin Finck         }
2228c2c66affSColin Finck     }
2229c2c66affSColin Finck     else
2230c2c66affSColin Finck     {
2231c2c66affSColin Finck         /*
2232c2c66affSColin Finck          * An necessary condition for Y and X = 2Y + 1 to be prime
2233c2c66affSColin Finck          * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2234c2c66affSColin Finck          * Make sure it is satisfied, while keeping X = 3 mod 4
2235c2c66affSColin Finck          */
2236c2c66affSColin Finck 
2237c2c66affSColin Finck         X->p[0] |= 2;
2238c2c66affSColin Finck 
2239c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2240c2c66affSColin Finck         if( r == 0 )
2241c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2242c2c66affSColin Finck         else if( r == 1 )
2243c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2244c2c66affSColin Finck 
2245c2c66affSColin Finck         /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2246c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2247c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2248c2c66affSColin Finck 
2249c2c66affSColin Finck         while( 1 )
2250c2c66affSColin Finck         {
2251c2c66affSColin Finck             /*
2252c2c66affSColin Finck              * First, check small factors for X and Y
2253c2c66affSColin Finck              * before doing Miller-Rabin on any of them
2254c2c66affSColin Finck              */
2255c2c66affSColin Finck             if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
2256c2c66affSColin Finck                 ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
2257c2c66affSColin Finck                 ( ret = mpi_miller_rabin(  X, f_rng, p_rng  ) ) == 0 &&
2258c2c66affSColin Finck                 ( ret = mpi_miller_rabin( &Y, f_rng, p_rng  ) ) == 0 )
2259c2c66affSColin Finck             {
2260c2c66affSColin Finck                 break;
2261c2c66affSColin Finck             }
2262c2c66affSColin Finck 
2263c2c66affSColin Finck             if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2264c2c66affSColin Finck                 goto cleanup;
2265c2c66affSColin Finck 
2266c2c66affSColin Finck             /*
2267c2c66affSColin Finck              * Next candidates. We want to preserve Y = (X-1) / 2 and
2268c2c66affSColin Finck              * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2269c2c66affSColin Finck              * so up Y by 6 and X by 12.
2270c2c66affSColin Finck              */
2271c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(  X,  X, 12 ) );
2272c2c66affSColin Finck             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6  ) );
2273c2c66affSColin Finck         }
2274c2c66affSColin Finck     }
2275c2c66affSColin Finck 
2276c2c66affSColin Finck cleanup:
2277c2c66affSColin Finck 
2278c2c66affSColin Finck     mbedtls_mpi_free( &Y );
2279c2c66affSColin Finck 
2280c2c66affSColin Finck     return( ret );
2281c2c66affSColin Finck }
2282c2c66affSColin Finck 
2283c2c66affSColin Finck #endif /* MBEDTLS_GENPRIME */
2284c2c66affSColin Finck 
2285c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST)
2286c2c66affSColin Finck 
2287c2c66affSColin Finck #define GCD_PAIR_COUNT  3
2288c2c66affSColin Finck 
2289c2c66affSColin Finck static const int gcd_pairs[GCD_PAIR_COUNT][3] =
2290c2c66affSColin Finck {
2291c2c66affSColin Finck     { 693, 609, 21 },
2292c2c66affSColin Finck     { 1764, 868, 28 },
2293c2c66affSColin Finck     { 768454923, 542167814, 1 }
2294c2c66affSColin Finck };
2295c2c66affSColin Finck 
2296c2c66affSColin Finck /*
2297c2c66affSColin Finck  * Checkup routine
2298c2c66affSColin Finck  */
2299c2c66affSColin Finck int mbedtls_mpi_self_test( int verbose )
2300c2c66affSColin Finck {
2301c2c66affSColin Finck     int ret, i;
2302c2c66affSColin Finck     mbedtls_mpi A, E, N, X, Y, U, V;
2303c2c66affSColin Finck 
2304c2c66affSColin Finck     mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X );
2305c2c66affSColin Finck     mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V );
2306c2c66affSColin Finck 
2307c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
2308c2c66affSColin Finck         "EFE021C2645FD1DC586E69184AF4A31E" \
2309c2c66affSColin Finck         "D5F53E93B5F123FA41680867BA110131" \
2310c2c66affSColin Finck         "944FE7952E2517337780CB0DB80E61AA" \
2311c2c66affSColin Finck         "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
2312c2c66affSColin Finck 
2313c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
2314c2c66affSColin Finck         "B2E7EFD37075B9F03FF989C7C5051C20" \
2315c2c66affSColin Finck         "34D2A323810251127E7BF8625A4F49A5" \
2316c2c66affSColin Finck         "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
2317c2c66affSColin Finck         "5B5C25763222FEFCCFC38B832366C29E" ) );
2318c2c66affSColin Finck 
2319c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
2320c2c66affSColin Finck         "0066A198186C18C10B2F5ED9B522752A" \
2321c2c66affSColin Finck         "9830B69916E535C8F047518A889A43A5" \
2322c2c66affSColin Finck         "94B6BED27A168D31D4A52F88925AA8F5" ) );
2323c2c66affSColin Finck 
2324c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
2325c2c66affSColin Finck 
2326c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2327c2c66affSColin Finck         "602AB7ECA597A3D6B56FF9829A5E8B85" \
2328c2c66affSColin Finck         "9E857EA95A03512E2BAE7391688D264A" \
2329c2c66affSColin Finck         "A5663B0341DB9CCFD2C4C5F421FEC814" \
2330c2c66affSColin Finck         "8001B72E848A38CAE1C65F78E56ABDEF" \
2331c2c66affSColin Finck         "E12D3C039B8A02D6BE593F0BBBDA56F1" \
2332c2c66affSColin Finck         "ECF677152EF804370C1A305CAF3B5BF1" \
2333c2c66affSColin Finck         "30879B56C61DE584A0F53A2447A51E" ) );
2334c2c66affSColin Finck 
2335c2c66affSColin Finck     if( verbose != 0 )
2336c2c66affSColin Finck         mbedtls_printf( "  MPI test #1 (mul_mpi): " );
2337c2c66affSColin Finck 
2338c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2339c2c66affSColin Finck     {
2340c2c66affSColin Finck         if( verbose != 0 )
2341c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2342c2c66affSColin Finck 
2343c2c66affSColin Finck         ret = 1;
2344c2c66affSColin Finck         goto cleanup;
2345c2c66affSColin Finck     }
2346c2c66affSColin Finck 
2347c2c66affSColin Finck     if( verbose != 0 )
2348c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2349c2c66affSColin Finck 
2350c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
2351c2c66affSColin Finck 
2352c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2353c2c66affSColin Finck         "256567336059E52CAE22925474705F39A94" ) );
2354c2c66affSColin Finck 
2355c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
2356c2c66affSColin Finck         "6613F26162223DF488E9CD48CC132C7A" \
2357c2c66affSColin Finck         "0AC93C701B001B092E4E5B9F73BCD27B" \
2358c2c66affSColin Finck         "9EE50D0657C77F374E903CDFA4C642" ) );
2359c2c66affSColin Finck 
2360c2c66affSColin Finck     if( verbose != 0 )
2361c2c66affSColin Finck         mbedtls_printf( "  MPI test #2 (div_mpi): " );
2362c2c66affSColin Finck 
2363c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
2364c2c66affSColin Finck         mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
2365c2c66affSColin Finck     {
2366c2c66affSColin Finck         if( verbose != 0 )
2367c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2368c2c66affSColin Finck 
2369c2c66affSColin Finck         ret = 1;
2370c2c66affSColin Finck         goto cleanup;
2371c2c66affSColin Finck     }
2372c2c66affSColin Finck 
2373c2c66affSColin Finck     if( verbose != 0 )
2374c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2375c2c66affSColin Finck 
2376c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
2377c2c66affSColin Finck 
2378c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2379c2c66affSColin Finck         "36E139AEA55215609D2816998ED020BB" \
2380c2c66affSColin Finck         "BD96C37890F65171D948E9BC7CBAA4D9" \
2381c2c66affSColin Finck         "325D24D6A3C12710F10A09FA08AB87" ) );
2382c2c66affSColin Finck 
2383c2c66affSColin Finck     if( verbose != 0 )
2384c2c66affSColin Finck         mbedtls_printf( "  MPI test #3 (exp_mod): " );
2385c2c66affSColin Finck 
2386c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2387c2c66affSColin Finck     {
2388c2c66affSColin Finck         if( verbose != 0 )
2389c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2390c2c66affSColin Finck 
2391c2c66affSColin Finck         ret = 1;
2392c2c66affSColin Finck         goto cleanup;
2393c2c66affSColin Finck     }
2394c2c66affSColin Finck 
2395c2c66affSColin Finck     if( verbose != 0 )
2396c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2397c2c66affSColin Finck 
2398c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
2399c2c66affSColin Finck 
2400c2c66affSColin Finck     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
2401c2c66affSColin Finck         "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
2402c2c66affSColin Finck         "C3DBA76456363A10869622EAC2DD84EC" \
2403c2c66affSColin Finck         "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
2404c2c66affSColin Finck 
2405c2c66affSColin Finck     if( verbose != 0 )
2406c2c66affSColin Finck         mbedtls_printf( "  MPI test #4 (inv_mod): " );
2407c2c66affSColin Finck 
2408c2c66affSColin Finck     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
2409c2c66affSColin Finck     {
2410c2c66affSColin Finck         if( verbose != 0 )
2411c2c66affSColin Finck             mbedtls_printf( "failed\n" );
2412c2c66affSColin Finck 
2413c2c66affSColin Finck         ret = 1;
2414c2c66affSColin Finck         goto cleanup;
2415c2c66affSColin Finck     }
2416c2c66affSColin Finck 
2417c2c66affSColin Finck     if( verbose != 0 )
2418c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2419c2c66affSColin Finck 
2420c2c66affSColin Finck     if( verbose != 0 )
2421c2c66affSColin Finck         mbedtls_printf( "  MPI test #5 (simple gcd): " );
2422c2c66affSColin Finck 
2423c2c66affSColin Finck     for( i = 0; i < GCD_PAIR_COUNT; i++ )
2424c2c66affSColin Finck     {
2425c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
2426c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
2427c2c66affSColin Finck 
2428c2c66affSColin Finck         MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
2429c2c66affSColin Finck 
2430c2c66affSColin Finck         if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2431c2c66affSColin Finck         {
2432c2c66affSColin Finck             if( verbose != 0 )
2433c2c66affSColin Finck                 mbedtls_printf( "failed at %d\n", i );
2434c2c66affSColin Finck 
2435c2c66affSColin Finck             ret = 1;
2436c2c66affSColin Finck             goto cleanup;
2437c2c66affSColin Finck         }
2438c2c66affSColin Finck     }
2439c2c66affSColin Finck 
2440c2c66affSColin Finck     if( verbose != 0 )
2441c2c66affSColin Finck         mbedtls_printf( "passed\n" );
2442c2c66affSColin Finck 
2443c2c66affSColin Finck cleanup:
2444c2c66affSColin Finck 
2445c2c66affSColin Finck     if( ret != 0 && verbose != 0 )
2446c2c66affSColin Finck         mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
2447c2c66affSColin Finck 
2448c2c66affSColin Finck     mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
2449c2c66affSColin Finck     mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
2450c2c66affSColin Finck 
2451c2c66affSColin Finck     if( verbose != 0 )
2452c2c66affSColin Finck         mbedtls_printf( "\n" );
2453c2c66affSColin Finck 
2454c2c66affSColin Finck     return( ret );
2455c2c66affSColin Finck }
2456c2c66affSColin Finck 
2457c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */
2458c2c66affSColin Finck 
2459c2c66affSColin Finck #endif /* MBEDTLS_BIGNUM_C */
2460