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