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