xref: /optee_os/lib/libmbedtls/mbedtls/library/bignum.c (revision 7901324d9530594155991c8b283023d567741cc7)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Multi-precision integer library
3817466cbSJens Wiklander  *
4*7901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5*7901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander 
20817466cbSJens Wiklander /*
21817466cbSJens Wiklander  *  The following sources were referenced in the design of this Multi-precision
22817466cbSJens Wiklander  *  Integer library:
23817466cbSJens Wiklander  *
24817466cbSJens Wiklander  *  [1] Handbook of Applied Cryptography - 1997
25817466cbSJens Wiklander  *      Menezes, van Oorschot and Vanstone
26817466cbSJens Wiklander  *
27817466cbSJens Wiklander  *  [2] Multi-Precision Math
28817466cbSJens Wiklander  *      Tom St Denis
29817466cbSJens Wiklander  *      https://github.com/libtom/libtommath/blob/develop/tommath.pdf
30817466cbSJens Wiklander  *
31817466cbSJens Wiklander  *  [3] GNU Multi-Precision Arithmetic Library
32817466cbSJens Wiklander  *      https://gmplib.org/manual/index.html
33817466cbSJens Wiklander  *
34817466cbSJens Wiklander  */
35817466cbSJens Wiklander 
36*7901324dSJerome Forissier #include "common.h"
37817466cbSJens Wiklander 
38817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C)
39817466cbSJens Wiklander 
40817466cbSJens Wiklander #include "mbedtls/bignum.h"
41817466cbSJens Wiklander #include "mbedtls/bn_mul.h"
423d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
4311fa71b9SJerome Forissier #include "mbedtls/error.h"
44817466cbSJens Wiklander 
45817466cbSJens Wiklander #include <string.h>
46817466cbSJens Wiklander 
47817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
48817466cbSJens Wiklander #include "mbedtls/platform.h"
49817466cbSJens Wiklander #else
50817466cbSJens Wiklander #include <stdio.h>
51817466cbSJens Wiklander #include <stdlib.h>
52817466cbSJens Wiklander #define mbedtls_printf     printf
53817466cbSJens Wiklander #define mbedtls_calloc    calloc
54817466cbSJens Wiklander #define mbedtls_free       free
55817466cbSJens Wiklander #endif
56817466cbSJens Wiklander 
5798bd5fe3SJens Wiklander #include <mempool.h>
58b99a4a18SJens Wiklander #include <util.h>
5998bd5fe3SJens Wiklander 
603d3b0591SJens Wiklander #define MPI_VALIDATE_RET( cond )                                       \
613d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
623d3b0591SJens Wiklander #define MPI_VALIDATE( cond )                                           \
633d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE( cond )
64817466cbSJens Wiklander 
65817466cbSJens Wiklander #define ciL    (sizeof(mbedtls_mpi_uint))         /* chars in limb  */
66817466cbSJens Wiklander #define biL    (ciL << 3)               /* bits  in limb  */
67817466cbSJens Wiklander #define biH    (ciL << 2)               /* half limb size */
68817466cbSJens Wiklander 
69817466cbSJens Wiklander #define MPI_SIZE_T_MAX  ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
70817466cbSJens Wiklander 
71817466cbSJens Wiklander /*
72817466cbSJens Wiklander  * Convert between bits/chars and number of limbs
73817466cbSJens Wiklander  * Divide first in order to avoid potential overflows
74817466cbSJens Wiklander  */
75817466cbSJens Wiklander #define BITS_TO_LIMBS(i)  ( (i) / biL + ( (i) % biL != 0 ) )
76817466cbSJens Wiklander #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
77817466cbSJens Wiklander 
7898bd5fe3SJens Wiklander void *mbedtls_mpi_mempool;
7998bd5fe3SJens Wiklander 
803d3b0591SJens Wiklander /* Implementation that should never be optimized out by the compiler */
813d3b0591SJens Wiklander static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
823d3b0591SJens Wiklander {
833d3b0591SJens Wiklander     mbedtls_platform_zeroize( v, ciL * n );
843d3b0591SJens Wiklander }
853d3b0591SJens Wiklander 
86817466cbSJens Wiklander /*
87817466cbSJens Wiklander  * Initialize one MPI
88817466cbSJens Wiklander  */
893d3b0591SJens Wiklander static void mpi_init( mbedtls_mpi *X, short use_mempool )
90817466cbSJens Wiklander {
913d3b0591SJens Wiklander     MPI_VALIDATE( X != NULL );
92817466cbSJens Wiklander 
933d3b0591SJens Wiklander     X->s = 1;
943d3b0591SJens Wiklander     X->use_mempool = use_mempool;
953d3b0591SJens Wiklander     X->n = 0;
963d3b0591SJens Wiklander     X->p = NULL;
97817466cbSJens Wiklander }
98817466cbSJens Wiklander 
9998bd5fe3SJens Wiklander void mbedtls_mpi_init( mbedtls_mpi *X )
10098bd5fe3SJens Wiklander {
1013d3b0591SJens Wiklander     mpi_init( X, 0 /*use_mempool*/ );
10298bd5fe3SJens Wiklander }
10398bd5fe3SJens Wiklander 
10498bd5fe3SJens Wiklander void mbedtls_mpi_init_mempool( mbedtls_mpi *X )
10598bd5fe3SJens Wiklander {
1063d3b0591SJens Wiklander     mpi_init( X, !!mbedtls_mpi_mempool /*use_mempool*/ );
10798bd5fe3SJens Wiklander }
10898bd5fe3SJens Wiklander 
109817466cbSJens Wiklander /*
110817466cbSJens Wiklander  * Unallocate one MPI
111817466cbSJens Wiklander  */
112817466cbSJens Wiklander void mbedtls_mpi_free( mbedtls_mpi *X )
113817466cbSJens Wiklander {
114817466cbSJens Wiklander     if( X == NULL )
115817466cbSJens Wiklander         return;
116817466cbSJens Wiklander 
117817466cbSJens Wiklander     if( X->p != NULL )
118817466cbSJens Wiklander     {
119817466cbSJens Wiklander         mbedtls_mpi_zeroize( X->p, X->n );
1203d3b0591SJens Wiklander         if( X->use_mempool )
12118c5148dSJens Wiklander             mempool_free( mbedtls_mpi_mempool, X->p );
1223d3b0591SJens Wiklander         else
1233d3b0591SJens Wiklander             mbedtls_free( X->p );
124817466cbSJens Wiklander     }
125817466cbSJens Wiklander 
126817466cbSJens Wiklander     X->s = 1;
127817466cbSJens Wiklander     X->n = 0;
1283d3b0591SJens Wiklander     X->p = NULL;
129817466cbSJens Wiklander }
130817466cbSJens Wiklander 
131817466cbSJens Wiklander /*
132817466cbSJens Wiklander  * Enlarge to the specified number of limbs
133817466cbSJens Wiklander  */
134817466cbSJens Wiklander int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
135817466cbSJens Wiklander {
136817466cbSJens Wiklander     mbedtls_mpi_uint *p;
1373d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
138817466cbSJens Wiklander 
139817466cbSJens Wiklander     if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
140817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
141817466cbSJens Wiklander 
1423d3b0591SJens Wiklander     if( X->n < nblimbs )
1433d3b0591SJens Wiklander     {
1443d3b0591SJens Wiklander         if( X->use_mempool )
1453d3b0591SJens Wiklander         {
1463d3b0591SJens Wiklander             p = mempool_alloc( mbedtls_mpi_mempool, nblimbs * ciL );
14718c5148dSJens Wiklander             if( p == NULL )
14818c5148dSJens Wiklander                 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
1493d3b0591SJens Wiklander             memset( p, 0, nblimbs * ciL );
1503d3b0591SJens Wiklander         }
1513d3b0591SJens Wiklander         else
1523d3b0591SJens Wiklander         {
1533d3b0591SJens Wiklander             p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL );
1543d3b0591SJens Wiklander             if( p == NULL )
1553d3b0591SJens Wiklander                 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
156817466cbSJens Wiklander         }
157817466cbSJens Wiklander 
1583d3b0591SJens Wiklander         if( X->p != NULL )
1593d3b0591SJens Wiklander         {
1603d3b0591SJens Wiklander             memcpy( p, X->p, X->n * ciL );
1613d3b0591SJens Wiklander             mbedtls_mpi_zeroize( X->p, X->n );
1623d3b0591SJens Wiklander             if( X->use_mempool )
16318c5148dSJens Wiklander                 mempool_free( mbedtls_mpi_mempool, X->p);
1643d3b0591SJens Wiklander             else
1653d3b0591SJens Wiklander                 mbedtls_free( X->p );
1663d3b0591SJens Wiklander         }
16718c5148dSJens Wiklander 
16818c5148dSJens Wiklander         X->n = nblimbs;
1693d3b0591SJens Wiklander         X->p = p;
1703d3b0591SJens Wiklander     }
171817466cbSJens Wiklander 
172817466cbSJens Wiklander     return( 0 );
173817466cbSJens Wiklander }
174817466cbSJens Wiklander 
175817466cbSJens Wiklander /*
176817466cbSJens Wiklander  * Resize down as much as possible,
177817466cbSJens Wiklander  * while keeping at least the specified number of limbs
178817466cbSJens Wiklander  */
179817466cbSJens Wiklander int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
180817466cbSJens Wiklander {
181817466cbSJens Wiklander     mbedtls_mpi_uint *p;
182817466cbSJens Wiklander     size_t i;
1833d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
1843d3b0591SJens Wiklander 
1853d3b0591SJens Wiklander     if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
1863d3b0591SJens Wiklander         return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
187817466cbSJens Wiklander 
1885b25c76aSJerome Forissier     /* Actually resize up if there are currently fewer than nblimbs limbs. */
189817466cbSJens Wiklander     if( X->n <= nblimbs )
190817466cbSJens Wiklander         return( mbedtls_mpi_grow( X, nblimbs ) );
1915b25c76aSJerome Forissier     /* After this point, then X->n > nblimbs and in particular X->n > 0. */
192817466cbSJens Wiklander 
193817466cbSJens Wiklander     for( i = X->n - 1; i > 0; i-- )
194817466cbSJens Wiklander         if( X->p[i] != 0 )
195817466cbSJens Wiklander             break;
196817466cbSJens Wiklander     i++;
197817466cbSJens Wiklander 
198817466cbSJens Wiklander     if( i < nblimbs )
199817466cbSJens Wiklander         i = nblimbs;
200817466cbSJens Wiklander 
2013d3b0591SJens Wiklander     if( X->use_mempool )
2023d3b0591SJens Wiklander     {
203ed3fa831SJerome Forissier         p = mempool_alloc( mbedtls_mpi_mempool, i * ciL );
2043d3b0591SJens Wiklander         if( p == NULL )
20598bd5fe3SJens Wiklander             return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
206ed3fa831SJerome Forissier         memset( p, 0, i * ciL );
20798bd5fe3SJens Wiklander     }
2083d3b0591SJens Wiklander     else
2093d3b0591SJens Wiklander     {
210ed3fa831SJerome Forissier         p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL );
2113d3b0591SJens Wiklander         if( p == NULL )
2123d3b0591SJens Wiklander             return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
2133d3b0591SJens Wiklander     }
21418c5148dSJens Wiklander 
215817466cbSJens Wiklander     if( X->p != NULL )
216817466cbSJens Wiklander     {
217817466cbSJens Wiklander         memcpy( p, X->p, i * ciL );
218817466cbSJens Wiklander         mbedtls_mpi_zeroize( X->p, X->n );
2193d3b0591SJens Wiklander         if( X->use_mempool )
22018c5148dSJens Wiklander             mempool_free( mbedtls_mpi_mempool, X->p );
2213d3b0591SJens Wiklander         else
2223d3b0591SJens Wiklander             mbedtls_free( X->p );
223817466cbSJens Wiklander     }
224817466cbSJens Wiklander 
22518c5148dSJens Wiklander     X->n = i;
2263d3b0591SJens Wiklander     X->p = p;
227817466cbSJens Wiklander 
228817466cbSJens Wiklander     return( 0 );
229817466cbSJens Wiklander }
230817466cbSJens Wiklander 
231*7901324dSJerome Forissier /* Resize X to have exactly n limbs and set it to 0. */
232*7901324dSJerome Forissier static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
233*7901324dSJerome Forissier {
234*7901324dSJerome Forissier     if( limbs == 0 )
235*7901324dSJerome Forissier     {
236*7901324dSJerome Forissier         mbedtls_mpi_free( X );
237*7901324dSJerome Forissier         return( 0 );
238*7901324dSJerome Forissier     }
239*7901324dSJerome Forissier     else if( X->n == limbs )
240*7901324dSJerome Forissier     {
241*7901324dSJerome Forissier         memset( X->p, 0, limbs * ciL );
242*7901324dSJerome Forissier         X->s = 1;
243*7901324dSJerome Forissier         return( 0 );
244*7901324dSJerome Forissier     }
245*7901324dSJerome Forissier     else
246*7901324dSJerome Forissier     {
247*7901324dSJerome Forissier         mbedtls_mpi_free( X );
248*7901324dSJerome Forissier         return( mbedtls_mpi_grow( X, limbs ) );
249*7901324dSJerome Forissier     }
250*7901324dSJerome Forissier }
251*7901324dSJerome Forissier 
252817466cbSJens Wiklander /*
253*7901324dSJerome Forissier  * Copy the contents of Y into X.
254*7901324dSJerome Forissier  *
255*7901324dSJerome Forissier  * This function is not constant-time. Leading zeros in Y may be removed.
256*7901324dSJerome Forissier  *
257*7901324dSJerome Forissier  * Ensure that X does not shrink. This is not guaranteed by the public API,
258*7901324dSJerome Forissier  * but some code in the bignum module relies on this property, for example
259*7901324dSJerome Forissier  * in mbedtls_mpi_exp_mod().
260817466cbSJens Wiklander  */
261817466cbSJens Wiklander int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
262817466cbSJens Wiklander {
2633d3b0591SJens Wiklander     int ret = 0;
264817466cbSJens Wiklander     size_t i;
2653d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
2663d3b0591SJens Wiklander     MPI_VALIDATE_RET( Y != NULL );
267817466cbSJens Wiklander 
268817466cbSJens Wiklander     if( X == Y )
269817466cbSJens Wiklander         return( 0 );
270817466cbSJens Wiklander 
2715b25c76aSJerome Forissier     if( Y->n == 0 )
272817466cbSJens Wiklander     {
273*7901324dSJerome Forissier         if( X->n != 0 )
274*7901324dSJerome Forissier         {
275*7901324dSJerome Forissier             X->s = 1;
276*7901324dSJerome Forissier             memset( X->p, 0, X->n * ciL );
277*7901324dSJerome Forissier         }
278817466cbSJens Wiklander         return( 0 );
279817466cbSJens Wiklander     }
280817466cbSJens Wiklander 
281817466cbSJens Wiklander     for( i = Y->n - 1; i > 0; i-- )
282817466cbSJens Wiklander         if( Y->p[i] != 0 )
283817466cbSJens Wiklander             break;
284817466cbSJens Wiklander     i++;
285817466cbSJens Wiklander 
286817466cbSJens Wiklander     X->s = Y->s;
287817466cbSJens Wiklander 
2883d3b0591SJens Wiklander     if( X->n < i )
2893d3b0591SJens Wiklander     {
290817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
2913d3b0591SJens Wiklander     }
2923d3b0591SJens Wiklander     else
2933d3b0591SJens Wiklander     {
2943d3b0591SJens Wiklander         memset( X->p + i, 0, ( X->n - i ) * ciL );
2953d3b0591SJens Wiklander     }
296817466cbSJens Wiklander 
297817466cbSJens Wiklander     memcpy( X->p, Y->p, i * ciL );
298817466cbSJens Wiklander 
299817466cbSJens Wiklander cleanup:
300817466cbSJens Wiklander 
301817466cbSJens Wiklander     return( ret );
302817466cbSJens Wiklander }
303817466cbSJens Wiklander 
304817466cbSJens Wiklander /*
305817466cbSJens Wiklander  * Swap the contents of X and Y
306817466cbSJens Wiklander  */
307817466cbSJens Wiklander void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
308817466cbSJens Wiklander {
309817466cbSJens Wiklander     mbedtls_mpi T;
3103d3b0591SJens Wiklander     MPI_VALIDATE( X != NULL );
3113d3b0591SJens Wiklander     MPI_VALIDATE( Y != NULL );
312817466cbSJens Wiklander 
313817466cbSJens Wiklander     memcpy( &T,  X, sizeof( mbedtls_mpi ) );
314817466cbSJens Wiklander     memcpy(  X,  Y, sizeof( mbedtls_mpi ) );
315817466cbSJens Wiklander     memcpy(  Y, &T, sizeof( mbedtls_mpi ) );
316817466cbSJens Wiklander }
317817466cbSJens Wiklander 
318*7901324dSJerome Forissier /**
319*7901324dSJerome Forissier  * Select between two sign values in constant-time.
320*7901324dSJerome Forissier  *
321*7901324dSJerome Forissier  * This is functionally equivalent to second ? a : b but uses only bit
322*7901324dSJerome Forissier  * operations in order to avoid branches.
323*7901324dSJerome Forissier  *
324*7901324dSJerome Forissier  * \param[in] a         The first sign; must be either +1 or -1.
325*7901324dSJerome Forissier  * \param[in] b         The second sign; must be either +1 or -1.
326*7901324dSJerome Forissier  * \param[in] second    Must be either 1 (return b) or 0 (return a).
327*7901324dSJerome Forissier  *
328*7901324dSJerome Forissier  * \return The selected sign value.
329*7901324dSJerome Forissier  */
330*7901324dSJerome Forissier static int mpi_safe_cond_select_sign( int a, int b, unsigned char second )
331*7901324dSJerome Forissier {
332*7901324dSJerome Forissier     /* In order to avoid questions about what we can reasonnably assume about
333*7901324dSJerome Forissier      * the representations of signed integers, move everything to unsigned
334*7901324dSJerome Forissier      * by taking advantage of the fact that a and b are either +1 or -1. */
335*7901324dSJerome Forissier     unsigned ua = a + 1;
336*7901324dSJerome Forissier     unsigned ub = b + 1;
337*7901324dSJerome Forissier 
338*7901324dSJerome Forissier     /* second was 0 or 1, mask is 0 or 2 as are ua and ub */
339*7901324dSJerome Forissier     const unsigned mask = second << 1;
340*7901324dSJerome Forissier 
341*7901324dSJerome Forissier     /* select ua or ub */
342*7901324dSJerome Forissier     unsigned ur = ( ua & ~mask ) | ( ub & mask );
343*7901324dSJerome Forissier 
344*7901324dSJerome Forissier     /* ur is now 0 or 2, convert back to -1 or +1 */
345*7901324dSJerome Forissier     return( (int) ur - 1 );
346*7901324dSJerome Forissier }
347*7901324dSJerome Forissier 
348*7901324dSJerome Forissier /*
349*7901324dSJerome Forissier  * Conditionally assign dest = src, without leaking information
350*7901324dSJerome Forissier  * about whether the assignment was made or not.
351*7901324dSJerome Forissier  * dest and src must be arrays of limbs of size n.
352*7901324dSJerome Forissier  * assign must be 0 or 1.
353*7901324dSJerome Forissier  */
354*7901324dSJerome Forissier static void mpi_safe_cond_assign( size_t n,
355*7901324dSJerome Forissier                                   mbedtls_mpi_uint *dest,
356*7901324dSJerome Forissier                                   const mbedtls_mpi_uint *src,
357*7901324dSJerome Forissier                                   unsigned char assign )
358*7901324dSJerome Forissier {
359*7901324dSJerome Forissier     size_t i;
360*7901324dSJerome Forissier 
361*7901324dSJerome Forissier     /* MSVC has a warning about unary minus on unsigned integer types,
362*7901324dSJerome Forissier      * but this is well-defined and precisely what we want to do here. */
363*7901324dSJerome Forissier #if defined(_MSC_VER)
364*7901324dSJerome Forissier #pragma warning( push )
365*7901324dSJerome Forissier #pragma warning( disable : 4146 )
366*7901324dSJerome Forissier #endif
367*7901324dSJerome Forissier 
368*7901324dSJerome Forissier     /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
369*7901324dSJerome Forissier     const mbedtls_mpi_uint mask = -assign;
370*7901324dSJerome Forissier 
371*7901324dSJerome Forissier #if defined(_MSC_VER)
372*7901324dSJerome Forissier #pragma warning( pop )
373*7901324dSJerome Forissier #endif
374*7901324dSJerome Forissier 
375*7901324dSJerome Forissier     for( i = 0; i < n; i++ )
376*7901324dSJerome Forissier         dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask );
377*7901324dSJerome Forissier }
378*7901324dSJerome Forissier 
379817466cbSJens Wiklander /*
380817466cbSJens Wiklander  * Conditionally assign X = Y, without leaking information
381817466cbSJens Wiklander  * about whether the assignment was made or not.
382817466cbSJens Wiklander  * (Leaking information about the respective sizes of X and Y is ok however.)
383817466cbSJens Wiklander  */
384817466cbSJens Wiklander int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign )
385817466cbSJens Wiklander {
386817466cbSJens Wiklander     int ret = 0;
387817466cbSJens Wiklander     size_t i;
388*7901324dSJerome Forissier     mbedtls_mpi_uint limb_mask;
3893d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
3903d3b0591SJens Wiklander     MPI_VALIDATE_RET( Y != NULL );
391817466cbSJens Wiklander 
392*7901324dSJerome Forissier     /* MSVC has a warning about unary minus on unsigned integer types,
393*7901324dSJerome Forissier      * but this is well-defined and precisely what we want to do here. */
394*7901324dSJerome Forissier #if defined(_MSC_VER)
395*7901324dSJerome Forissier #pragma warning( push )
396*7901324dSJerome Forissier #pragma warning( disable : 4146 )
397*7901324dSJerome Forissier #endif
398*7901324dSJerome Forissier 
399817466cbSJens Wiklander     /* make sure assign is 0 or 1 in a time-constant manner */
400*7901324dSJerome Forissier     assign = (assign | (unsigned char)-assign) >> (sizeof( assign ) * 8 - 1);
401*7901324dSJerome Forissier     /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
402*7901324dSJerome Forissier     limb_mask = -assign;
403*7901324dSJerome Forissier 
404*7901324dSJerome Forissier #if defined(_MSC_VER)
405*7901324dSJerome Forissier #pragma warning( pop )
406*7901324dSJerome Forissier #endif
407817466cbSJens Wiklander 
408817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
409817466cbSJens Wiklander 
410*7901324dSJerome Forissier     X->s = mpi_safe_cond_select_sign( X->s, Y->s, assign );
411817466cbSJens Wiklander 
412*7901324dSJerome Forissier     mpi_safe_cond_assign( Y->n, X->p, Y->p, assign );
413817466cbSJens Wiklander 
414*7901324dSJerome Forissier     for( i = Y->n; i < X->n; i++ )
415*7901324dSJerome Forissier         X->p[i] &= ~limb_mask;
416817466cbSJens Wiklander 
417817466cbSJens Wiklander cleanup:
418817466cbSJens Wiklander     return( ret );
419817466cbSJens Wiklander }
420817466cbSJens Wiklander 
421817466cbSJens Wiklander /*
422817466cbSJens Wiklander  * Conditionally swap X and Y, without leaking information
423817466cbSJens Wiklander  * about whether the swap was made or not.
424817466cbSJens Wiklander  * Here it is not ok to simply swap the pointers, which whould lead to
425817466cbSJens Wiklander  * different memory access patterns when X and Y are used afterwards.
426817466cbSJens Wiklander  */
427817466cbSJens Wiklander int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap )
428817466cbSJens Wiklander {
429817466cbSJens Wiklander     int ret, s;
430817466cbSJens Wiklander     size_t i;
431*7901324dSJerome Forissier     mbedtls_mpi_uint limb_mask;
432817466cbSJens Wiklander     mbedtls_mpi_uint tmp;
4333d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
4343d3b0591SJens Wiklander     MPI_VALIDATE_RET( Y != NULL );
435817466cbSJens Wiklander 
436817466cbSJens Wiklander     if( X == Y )
437817466cbSJens Wiklander         return( 0 );
438817466cbSJens Wiklander 
439*7901324dSJerome Forissier     /* MSVC has a warning about unary minus on unsigned integer types,
440*7901324dSJerome Forissier      * but this is well-defined and precisely what we want to do here. */
441*7901324dSJerome Forissier #if defined(_MSC_VER)
442*7901324dSJerome Forissier #pragma warning( push )
443*7901324dSJerome Forissier #pragma warning( disable : 4146 )
444*7901324dSJerome Forissier #endif
445*7901324dSJerome Forissier 
446817466cbSJens Wiklander     /* make sure swap is 0 or 1 in a time-constant manner */
447*7901324dSJerome Forissier     swap = (swap | (unsigned char)-swap) >> (sizeof( swap ) * 8 - 1);
448*7901324dSJerome Forissier     /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
449*7901324dSJerome Forissier     limb_mask = -swap;
450*7901324dSJerome Forissier 
451*7901324dSJerome Forissier #if defined(_MSC_VER)
452*7901324dSJerome Forissier #pragma warning( pop )
453*7901324dSJerome Forissier #endif
454817466cbSJens Wiklander 
455817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) );
456817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) );
457817466cbSJens Wiklander 
458817466cbSJens Wiklander     s = X->s;
459*7901324dSJerome Forissier     X->s = mpi_safe_cond_select_sign( X->s, Y->s, swap );
460*7901324dSJerome Forissier     Y->s = mpi_safe_cond_select_sign( Y->s, s, swap );
461817466cbSJens Wiklander 
462817466cbSJens Wiklander 
463817466cbSJens Wiklander     for( i = 0; i < X->n; i++ )
464817466cbSJens Wiklander     {
465817466cbSJens Wiklander         tmp = X->p[i];
466*7901324dSJerome Forissier         X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask );
467*7901324dSJerome Forissier         Y->p[i] = ( Y->p[i] & ~limb_mask ) | (     tmp & limb_mask );
468817466cbSJens Wiklander     }
469817466cbSJens Wiklander 
470817466cbSJens Wiklander cleanup:
471817466cbSJens Wiklander     return( ret );
472817466cbSJens Wiklander }
473817466cbSJens Wiklander 
474817466cbSJens Wiklander /*
475817466cbSJens Wiklander  * Set value from integer
476817466cbSJens Wiklander  */
477817466cbSJens Wiklander int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
478817466cbSJens Wiklander {
47911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4803d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
481817466cbSJens Wiklander 
482817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
483817466cbSJens Wiklander     memset( X->p, 0, X->n * ciL );
484817466cbSJens Wiklander 
485817466cbSJens Wiklander     X->p[0] = ( z < 0 ) ? -z : z;
486817466cbSJens Wiklander     X->s    = ( z < 0 ) ? -1 : 1;
487817466cbSJens Wiklander 
488817466cbSJens Wiklander cleanup:
489817466cbSJens Wiklander 
490817466cbSJens Wiklander     return( ret );
491817466cbSJens Wiklander }
492817466cbSJens Wiklander 
493817466cbSJens Wiklander /*
494817466cbSJens Wiklander  * Get a specific bit
495817466cbSJens Wiklander  */
496817466cbSJens Wiklander int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
497817466cbSJens Wiklander {
4983d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
4993d3b0591SJens Wiklander 
500817466cbSJens Wiklander     if( X->n * biL <= pos )
501817466cbSJens Wiklander         return( 0 );
502817466cbSJens Wiklander 
503817466cbSJens Wiklander     return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
504817466cbSJens Wiklander }
505817466cbSJens Wiklander 
5063d3b0591SJens Wiklander /* Get a specific byte, without range checks. */
5073d3b0591SJens Wiklander #define GET_BYTE( X, i )                                \
5083d3b0591SJens Wiklander     ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
5093d3b0591SJens Wiklander 
510817466cbSJens Wiklander /*
511817466cbSJens Wiklander  * Set a bit to a specific value of 0 or 1
512817466cbSJens Wiklander  */
513817466cbSJens Wiklander int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
514817466cbSJens Wiklander {
515817466cbSJens Wiklander     int ret = 0;
516817466cbSJens Wiklander     size_t off = pos / biL;
517817466cbSJens Wiklander     size_t idx = pos % biL;
5183d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
519817466cbSJens Wiklander 
520817466cbSJens Wiklander     if( val != 0 && val != 1 )
521817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
522817466cbSJens Wiklander 
523817466cbSJens Wiklander     if( X->n * biL <= pos )
524817466cbSJens Wiklander     {
525817466cbSJens Wiklander         if( val == 0 )
526817466cbSJens Wiklander             return( 0 );
527817466cbSJens Wiklander 
528817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
529817466cbSJens Wiklander     }
530817466cbSJens Wiklander 
531817466cbSJens Wiklander     X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
532817466cbSJens Wiklander     X->p[off] |= (mbedtls_mpi_uint) val << idx;
533817466cbSJens Wiklander 
534817466cbSJens Wiklander cleanup:
535817466cbSJens Wiklander 
536817466cbSJens Wiklander     return( ret );
537817466cbSJens Wiklander }
538817466cbSJens Wiklander 
539817466cbSJens Wiklander /*
540817466cbSJens Wiklander  * Return the number of less significant zero-bits
541817466cbSJens Wiklander  */
542817466cbSJens Wiklander size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
543817466cbSJens Wiklander {
544817466cbSJens Wiklander     size_t i, j, count = 0;
5453d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
546817466cbSJens Wiklander 
547817466cbSJens Wiklander     for( i = 0; i < X->n; i++ )
548817466cbSJens Wiklander         for( j = 0; j < biL; j++, count++ )
549817466cbSJens Wiklander             if( ( ( X->p[i] >> j ) & 1 ) != 0 )
550817466cbSJens Wiklander                 return( count );
551817466cbSJens Wiklander 
552817466cbSJens Wiklander     return( 0 );
553817466cbSJens Wiklander }
554817466cbSJens Wiklander 
555817466cbSJens Wiklander /*
556817466cbSJens Wiklander  * Count leading zero bits in a given integer
557817466cbSJens Wiklander  */
558817466cbSJens Wiklander static size_t mbedtls_clz( const mbedtls_mpi_uint x )
559817466cbSJens Wiklander {
560817466cbSJens Wiklander     size_t j;
561817466cbSJens Wiklander     mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
562817466cbSJens Wiklander 
563817466cbSJens Wiklander     for( j = 0; j < biL; j++ )
564817466cbSJens Wiklander     {
565817466cbSJens Wiklander         if( x & mask ) break;
566817466cbSJens Wiklander 
567817466cbSJens Wiklander         mask >>= 1;
568817466cbSJens Wiklander     }
569817466cbSJens Wiklander 
570817466cbSJens Wiklander     return j;
571817466cbSJens Wiklander }
572817466cbSJens Wiklander 
573817466cbSJens Wiklander /*
574817466cbSJens Wiklander  * Return the number of bits
575817466cbSJens Wiklander  */
576817466cbSJens Wiklander size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
577817466cbSJens Wiklander {
578817466cbSJens Wiklander     size_t i, j;
579817466cbSJens Wiklander 
580817466cbSJens Wiklander     if( X->n == 0 )
581817466cbSJens Wiklander         return( 0 );
582817466cbSJens Wiklander 
583817466cbSJens Wiklander     for( i = X->n - 1; i > 0; i-- )
584817466cbSJens Wiklander         if( X->p[i] != 0 )
585817466cbSJens Wiklander             break;
586817466cbSJens Wiklander 
587817466cbSJens Wiklander     j = biL - mbedtls_clz( X->p[i] );
588817466cbSJens Wiklander 
589817466cbSJens Wiklander     return( ( i * biL ) + j );
590817466cbSJens Wiklander }
591817466cbSJens Wiklander 
592817466cbSJens Wiklander /*
593817466cbSJens Wiklander  * Return the total size in bytes
594817466cbSJens Wiklander  */
595817466cbSJens Wiklander size_t mbedtls_mpi_size( const mbedtls_mpi *X )
596817466cbSJens Wiklander {
597817466cbSJens Wiklander     return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
598817466cbSJens Wiklander }
599817466cbSJens Wiklander 
600817466cbSJens Wiklander /*
601817466cbSJens Wiklander  * Convert an ASCII character to digit value
602817466cbSJens Wiklander  */
603817466cbSJens Wiklander static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
604817466cbSJens Wiklander {
605817466cbSJens Wiklander     *d = 255;
606817466cbSJens Wiklander 
607817466cbSJens Wiklander     if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
608817466cbSJens Wiklander     if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
609817466cbSJens Wiklander     if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
610817466cbSJens Wiklander 
611817466cbSJens Wiklander     if( *d >= (mbedtls_mpi_uint) radix )
612817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
613817466cbSJens Wiklander 
614817466cbSJens Wiklander     return( 0 );
615817466cbSJens Wiklander }
616817466cbSJens Wiklander 
617817466cbSJens Wiklander /*
618817466cbSJens Wiklander  * Import from an ASCII string
619817466cbSJens Wiklander  */
620817466cbSJens Wiklander int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
621817466cbSJens Wiklander {
62211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
623817466cbSJens Wiklander     size_t i, j, slen, n;
624*7901324dSJerome Forissier     int sign = 1;
625817466cbSJens Wiklander     mbedtls_mpi_uint d;
626817466cbSJens Wiklander     mbedtls_mpi T;
6273d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
6283d3b0591SJens Wiklander     MPI_VALIDATE_RET( s != NULL );
629817466cbSJens Wiklander 
630817466cbSJens Wiklander     if( radix < 2 || radix > 16 )
631817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
632817466cbSJens Wiklander 
63398bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &T );
634817466cbSJens Wiklander 
635*7901324dSJerome Forissier     if( s[0] == 0 )
636*7901324dSJerome Forissier     {
637*7901324dSJerome Forissier         mbedtls_mpi_free( X );
638*7901324dSJerome Forissier         return( 0 );
639*7901324dSJerome Forissier     }
640*7901324dSJerome Forissier 
641*7901324dSJerome Forissier     if( s[0] == '-' )
642*7901324dSJerome Forissier     {
643*7901324dSJerome Forissier         ++s;
644*7901324dSJerome Forissier         sign = -1;
645*7901324dSJerome Forissier     }
646*7901324dSJerome Forissier 
647817466cbSJens Wiklander     slen = strlen( s );
648817466cbSJens Wiklander 
649817466cbSJens Wiklander     if( radix == 16 )
650817466cbSJens Wiklander     {
651817466cbSJens Wiklander         if( slen > MPI_SIZE_T_MAX >> 2 )
652817466cbSJens Wiklander             return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
653817466cbSJens Wiklander 
654817466cbSJens Wiklander         n = BITS_TO_LIMBS( slen << 2 );
655817466cbSJens Wiklander 
656817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
657817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
658817466cbSJens Wiklander 
659817466cbSJens Wiklander         for( i = slen, j = 0; i > 0; i--, j++ )
660817466cbSJens Wiklander         {
661817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
662817466cbSJens Wiklander             X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
663817466cbSJens Wiklander         }
664817466cbSJens Wiklander     }
665817466cbSJens Wiklander     else
666817466cbSJens Wiklander     {
667817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
668817466cbSJens Wiklander 
669817466cbSJens Wiklander         for( i = 0; i < slen; i++ )
670817466cbSJens Wiklander         {
671817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
672817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
673817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
674817466cbSJens Wiklander         }
675817466cbSJens Wiklander     }
676*7901324dSJerome Forissier 
677*7901324dSJerome Forissier     if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
678*7901324dSJerome Forissier         X->s = -1;
679817466cbSJens Wiklander 
680817466cbSJens Wiklander cleanup:
681817466cbSJens Wiklander 
682817466cbSJens Wiklander     mbedtls_mpi_free( &T );
683817466cbSJens Wiklander 
684817466cbSJens Wiklander     return( ret );
685817466cbSJens Wiklander }
686817466cbSJens Wiklander 
687817466cbSJens Wiklander /*
6885b25c76aSJerome Forissier  * Helper to write the digits high-order first.
689817466cbSJens Wiklander  */
6905b25c76aSJerome Forissier static int mpi_write_hlp( mbedtls_mpi *X, int radix,
6915b25c76aSJerome Forissier                           char **p, const size_t buflen )
692817466cbSJens Wiklander {
69311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
694817466cbSJens Wiklander     mbedtls_mpi_uint r;
6955b25c76aSJerome Forissier     size_t length = 0;
6965b25c76aSJerome Forissier     char *p_end = *p + buflen;
697817466cbSJens Wiklander 
6985b25c76aSJerome Forissier     do
6995b25c76aSJerome Forissier     {
7005b25c76aSJerome Forissier         if( length >= buflen )
7015b25c76aSJerome Forissier         {
7025b25c76aSJerome Forissier             return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
7035b25c76aSJerome Forissier         }
704817466cbSJens Wiklander 
705817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
706817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
7075b25c76aSJerome Forissier         /*
7085b25c76aSJerome Forissier          * Write the residue in the current position, as an ASCII character.
7095b25c76aSJerome Forissier          */
7105b25c76aSJerome Forissier         if( r < 0xA )
7115b25c76aSJerome Forissier             *(--p_end) = (char)( '0' + r );
712817466cbSJens Wiklander         else
7135b25c76aSJerome Forissier             *(--p_end) = (char)( 'A' + ( r - 0xA ) );
7145b25c76aSJerome Forissier 
7155b25c76aSJerome Forissier         length++;
7165b25c76aSJerome Forissier     } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
7175b25c76aSJerome Forissier 
7185b25c76aSJerome Forissier     memmove( *p, p_end, length );
7195b25c76aSJerome Forissier     *p += length;
720817466cbSJens Wiklander 
721817466cbSJens Wiklander cleanup:
722817466cbSJens Wiklander 
723817466cbSJens Wiklander     return( ret );
724817466cbSJens Wiklander }
725817466cbSJens Wiklander 
726817466cbSJens Wiklander /*
727817466cbSJens Wiklander  * Export into an ASCII string
728817466cbSJens Wiklander  */
729817466cbSJens Wiklander int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
730817466cbSJens Wiklander                               char *buf, size_t buflen, size_t *olen )
731817466cbSJens Wiklander {
732817466cbSJens Wiklander     int ret = 0;
733817466cbSJens Wiklander     size_t n;
734817466cbSJens Wiklander     char *p;
735817466cbSJens Wiklander     mbedtls_mpi T;
7363d3b0591SJens Wiklander     MPI_VALIDATE_RET( X    != NULL );
7373d3b0591SJens Wiklander     MPI_VALIDATE_RET( olen != NULL );
7383d3b0591SJens Wiklander     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
739817466cbSJens Wiklander 
740817466cbSJens Wiklander     if( radix < 2 || radix > 16 )
741817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
742817466cbSJens Wiklander 
7435b25c76aSJerome Forissier     n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
7445b25c76aSJerome Forissier     if( radix >=  4 ) n >>= 1;   /* Number of 4-adic digits necessary to present
7455b25c76aSJerome Forissier                                   * `n`. If radix > 4, this might be a strict
7465b25c76aSJerome Forissier                                   * overapproximation of the number of
7475b25c76aSJerome Forissier                                   * radix-adic digits needed to present `n`. */
7485b25c76aSJerome Forissier     if( radix >= 16 ) n >>= 1;   /* Number of hexadecimal digits necessary to
7495b25c76aSJerome Forissier                                   * present `n`. */
7505b25c76aSJerome Forissier 
7515b25c76aSJerome Forissier     n += 1; /* Terminating null byte */
7525b25c76aSJerome Forissier     n += 1; /* Compensate for the divisions above, which round down `n`
7535b25c76aSJerome Forissier              * in case it's not even. */
7545b25c76aSJerome Forissier     n += 1; /* Potential '-'-sign. */
7555b25c76aSJerome Forissier     n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
7565b25c76aSJerome Forissier                      * which always uses an even number of hex-digits. */
757817466cbSJens Wiklander 
758817466cbSJens Wiklander     if( buflen < n )
759817466cbSJens Wiklander     {
760817466cbSJens Wiklander         *olen = n;
761817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
762817466cbSJens Wiklander     }
763817466cbSJens Wiklander 
764817466cbSJens Wiklander     p = buf;
76598bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &T );
766817466cbSJens Wiklander 
767817466cbSJens Wiklander     if( X->s == -1 )
7685b25c76aSJerome Forissier     {
769817466cbSJens Wiklander         *p++ = '-';
7705b25c76aSJerome Forissier         buflen--;
7715b25c76aSJerome Forissier     }
772817466cbSJens Wiklander 
773817466cbSJens Wiklander     if( radix == 16 )
774817466cbSJens Wiklander     {
775817466cbSJens Wiklander         int c;
776817466cbSJens Wiklander         size_t i, j, k;
777817466cbSJens Wiklander 
778817466cbSJens Wiklander         for( i = X->n, k = 0; i > 0; i-- )
779817466cbSJens Wiklander         {
780817466cbSJens Wiklander             for( j = ciL; j > 0; j-- )
781817466cbSJens Wiklander             {
782817466cbSJens Wiklander                 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
783817466cbSJens Wiklander 
784817466cbSJens Wiklander                 if( c == 0 && k == 0 && ( i + j ) != 2 )
785817466cbSJens Wiklander                     continue;
786817466cbSJens Wiklander 
787817466cbSJens Wiklander                 *(p++) = "0123456789ABCDEF" [c / 16];
788817466cbSJens Wiklander                 *(p++) = "0123456789ABCDEF" [c % 16];
789817466cbSJens Wiklander                 k = 1;
790817466cbSJens Wiklander             }
791817466cbSJens Wiklander         }
792817466cbSJens Wiklander     }
793817466cbSJens Wiklander     else
794817466cbSJens Wiklander     {
795817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
796817466cbSJens Wiklander 
797817466cbSJens Wiklander         if( T.s == -1 )
798817466cbSJens Wiklander             T.s = 1;
799817466cbSJens Wiklander 
8005b25c76aSJerome Forissier         MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
801817466cbSJens Wiklander     }
802817466cbSJens Wiklander 
803817466cbSJens Wiklander     *p++ = '\0';
804817466cbSJens Wiklander     *olen = p - buf;
805817466cbSJens Wiklander 
806817466cbSJens Wiklander cleanup:
807817466cbSJens Wiklander 
808817466cbSJens Wiklander     mbedtls_mpi_free( &T );
809817466cbSJens Wiklander 
810817466cbSJens Wiklander     return( ret );
811817466cbSJens Wiklander }
812817466cbSJens Wiklander 
813817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
814817466cbSJens Wiklander /*
815817466cbSJens Wiklander  * Read X from an opened file
816817466cbSJens Wiklander  */
817817466cbSJens Wiklander int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
818817466cbSJens Wiklander {
819817466cbSJens Wiklander     mbedtls_mpi_uint d;
820817466cbSJens Wiklander     size_t slen;
821817466cbSJens Wiklander     char *p;
822817466cbSJens Wiklander     /*
823817466cbSJens Wiklander      * Buffer should have space for (short) label and decimal formatted MPI,
824817466cbSJens Wiklander      * newline characters and '\0'
825817466cbSJens Wiklander      */
826817466cbSJens Wiklander     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
827817466cbSJens Wiklander 
8283d3b0591SJens Wiklander     MPI_VALIDATE_RET( X   != NULL );
8293d3b0591SJens Wiklander     MPI_VALIDATE_RET( fin != NULL );
8303d3b0591SJens Wiklander 
8313d3b0591SJens Wiklander     if( radix < 2 || radix > 16 )
8323d3b0591SJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
8333d3b0591SJens Wiklander 
834817466cbSJens Wiklander     memset( s, 0, sizeof( s ) );
835817466cbSJens Wiklander     if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
836817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
837817466cbSJens Wiklander 
838817466cbSJens Wiklander     slen = strlen( s );
839817466cbSJens Wiklander     if( slen == sizeof( s ) - 2 )
840817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
841817466cbSJens Wiklander 
842817466cbSJens Wiklander     if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
843817466cbSJens Wiklander     if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
844817466cbSJens Wiklander 
845817466cbSJens Wiklander     p = s + slen;
846817466cbSJens Wiklander     while( p-- > s )
847817466cbSJens Wiklander         if( mpi_get_digit( &d, radix, *p ) != 0 )
848817466cbSJens Wiklander             break;
849817466cbSJens Wiklander 
850817466cbSJens Wiklander     return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
851817466cbSJens Wiklander }
852817466cbSJens Wiklander 
853817466cbSJens Wiklander /*
854817466cbSJens Wiklander  * Write X into an opened file (or stdout if fout == NULL)
855817466cbSJens Wiklander  */
856817466cbSJens Wiklander int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
857817466cbSJens Wiklander {
85811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
859817466cbSJens Wiklander     size_t n, slen, plen;
860817466cbSJens Wiklander     /*
861817466cbSJens Wiklander      * Buffer should have space for (short) label and decimal formatted MPI,
862817466cbSJens Wiklander      * newline characters and '\0'
863817466cbSJens Wiklander      */
864817466cbSJens Wiklander     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
8653d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
8663d3b0591SJens Wiklander 
8673d3b0591SJens Wiklander     if( radix < 2 || radix > 16 )
8683d3b0591SJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
869817466cbSJens Wiklander 
870817466cbSJens Wiklander     memset( s, 0, sizeof( s ) );
871817466cbSJens Wiklander 
872817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
873817466cbSJens Wiklander 
874817466cbSJens Wiklander     if( p == NULL ) p = "";
875817466cbSJens Wiklander 
876817466cbSJens Wiklander     plen = strlen( p );
877817466cbSJens Wiklander     slen = strlen( s );
878817466cbSJens Wiklander     s[slen++] = '\r';
879817466cbSJens Wiklander     s[slen++] = '\n';
880817466cbSJens Wiklander 
881817466cbSJens Wiklander     if( fout != NULL )
882817466cbSJens Wiklander     {
883817466cbSJens Wiklander         if( fwrite( p, 1, plen, fout ) != plen ||
884817466cbSJens Wiklander             fwrite( s, 1, slen, fout ) != slen )
885817466cbSJens Wiklander             return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
886817466cbSJens Wiklander     }
887817466cbSJens Wiklander     else
888817466cbSJens Wiklander         mbedtls_printf( "%s%s", p, s );
889817466cbSJens Wiklander 
890817466cbSJens Wiklander cleanup:
891817466cbSJens Wiklander 
892817466cbSJens Wiklander     return( ret );
893817466cbSJens Wiklander }
894817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
895817466cbSJens Wiklander 
8965b25c76aSJerome Forissier 
8975b25c76aSJerome Forissier /* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
8985b25c76aSJerome Forissier  * into the storage form used by mbedtls_mpi. */
8995b25c76aSJerome Forissier 
9005b25c76aSJerome Forissier static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
9015b25c76aSJerome Forissier {
9025b25c76aSJerome Forissier     uint8_t i;
9035b25c76aSJerome Forissier     unsigned char *x_ptr;
9045b25c76aSJerome Forissier     mbedtls_mpi_uint tmp = 0;
9055b25c76aSJerome Forissier 
9065b25c76aSJerome Forissier     for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
9075b25c76aSJerome Forissier     {
9085b25c76aSJerome Forissier         tmp <<= CHAR_BIT;
9095b25c76aSJerome Forissier         tmp |= (mbedtls_mpi_uint) *x_ptr;
9105b25c76aSJerome Forissier     }
9115b25c76aSJerome Forissier 
9125b25c76aSJerome Forissier     return( tmp );
9135b25c76aSJerome Forissier }
9145b25c76aSJerome Forissier 
9155b25c76aSJerome Forissier static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
9165b25c76aSJerome Forissier {
9175b25c76aSJerome Forissier #if defined(__BYTE_ORDER__)
9185b25c76aSJerome Forissier 
9195b25c76aSJerome Forissier /* Nothing to do on bigendian systems. */
9205b25c76aSJerome Forissier #if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
9215b25c76aSJerome Forissier     return( x );
9225b25c76aSJerome Forissier #endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
9235b25c76aSJerome Forissier 
9245b25c76aSJerome Forissier #if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
9255b25c76aSJerome Forissier 
9265b25c76aSJerome Forissier /* For GCC and Clang, have builtins for byte swapping. */
9275b25c76aSJerome Forissier #if defined(__GNUC__) && defined(__GNUC_PREREQ)
9285b25c76aSJerome Forissier #if __GNUC_PREREQ(4,3)
9295b25c76aSJerome Forissier #define have_bswap
9305b25c76aSJerome Forissier #endif
9315b25c76aSJerome Forissier #endif
9325b25c76aSJerome Forissier 
9335b25c76aSJerome Forissier #if defined(__clang__) && defined(__has_builtin)
9345b25c76aSJerome Forissier #if __has_builtin(__builtin_bswap32)  &&                 \
9355b25c76aSJerome Forissier     __has_builtin(__builtin_bswap64)
9365b25c76aSJerome Forissier #define have_bswap
9375b25c76aSJerome Forissier #endif
9385b25c76aSJerome Forissier #endif
9395b25c76aSJerome Forissier 
9405b25c76aSJerome Forissier #if defined(have_bswap)
9415b25c76aSJerome Forissier     /* The compiler is hopefully able to statically evaluate this! */
9425b25c76aSJerome Forissier     switch( sizeof(mbedtls_mpi_uint) )
9435b25c76aSJerome Forissier     {
9445b25c76aSJerome Forissier         case 4:
9455b25c76aSJerome Forissier             return( __builtin_bswap32(x) );
9465b25c76aSJerome Forissier         case 8:
9475b25c76aSJerome Forissier             return( __builtin_bswap64(x) );
9485b25c76aSJerome Forissier     }
9495b25c76aSJerome Forissier #endif
9505b25c76aSJerome Forissier #endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
9515b25c76aSJerome Forissier #endif /* __BYTE_ORDER__ */
9525b25c76aSJerome Forissier 
9535b25c76aSJerome Forissier     /* Fall back to C-based reordering if we don't know the byte order
9545b25c76aSJerome Forissier      * or we couldn't use a compiler-specific builtin. */
9555b25c76aSJerome Forissier     return( mpi_uint_bigendian_to_host_c( x ) );
9565b25c76aSJerome Forissier }
9575b25c76aSJerome Forissier 
9585b25c76aSJerome Forissier static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
9595b25c76aSJerome Forissier {
9605b25c76aSJerome Forissier     mbedtls_mpi_uint *cur_limb_left;
9615b25c76aSJerome Forissier     mbedtls_mpi_uint *cur_limb_right;
9625b25c76aSJerome Forissier     if( limbs == 0 )
9635b25c76aSJerome Forissier         return;
9645b25c76aSJerome Forissier 
9655b25c76aSJerome Forissier     /*
9665b25c76aSJerome Forissier      * Traverse limbs and
9675b25c76aSJerome Forissier      * - adapt byte-order in each limb
9685b25c76aSJerome Forissier      * - swap the limbs themselves.
9695b25c76aSJerome Forissier      * For that, simultaneously traverse the limbs from left to right
9705b25c76aSJerome Forissier      * and from right to left, as long as the left index is not bigger
9715b25c76aSJerome Forissier      * than the right index (it's not a problem if limbs is odd and the
9725b25c76aSJerome Forissier      * indices coincide in the last iteration).
9735b25c76aSJerome Forissier      */
9745b25c76aSJerome Forissier     for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
9755b25c76aSJerome Forissier          cur_limb_left <= cur_limb_right;
9765b25c76aSJerome Forissier          cur_limb_left++, cur_limb_right-- )
9775b25c76aSJerome Forissier     {
9785b25c76aSJerome Forissier         mbedtls_mpi_uint tmp;
9795b25c76aSJerome Forissier         /* Note that if cur_limb_left == cur_limb_right,
9805b25c76aSJerome Forissier          * this code effectively swaps the bytes only once. */
9815b25c76aSJerome Forissier         tmp             = mpi_uint_bigendian_to_host( *cur_limb_left  );
9825b25c76aSJerome Forissier         *cur_limb_left  = mpi_uint_bigendian_to_host( *cur_limb_right );
9835b25c76aSJerome Forissier         *cur_limb_right = tmp;
9845b25c76aSJerome Forissier     }
9855b25c76aSJerome Forissier }
9865b25c76aSJerome Forissier 
987817466cbSJens Wiklander /*
98811fa71b9SJerome Forissier  * Import X from unsigned binary data, little endian
98911fa71b9SJerome Forissier  */
99011fa71b9SJerome Forissier int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
99111fa71b9SJerome Forissier                                 const unsigned char *buf, size_t buflen )
99211fa71b9SJerome Forissier {
99311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
99411fa71b9SJerome Forissier     size_t i;
99511fa71b9SJerome Forissier     size_t const limbs = CHARS_TO_LIMBS( buflen );
99611fa71b9SJerome Forissier 
99711fa71b9SJerome Forissier     /* Ensure that target MPI has exactly the necessary number of limbs */
998*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
99911fa71b9SJerome Forissier 
100011fa71b9SJerome Forissier     for( i = 0; i < buflen; i++ )
100111fa71b9SJerome Forissier         X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
100211fa71b9SJerome Forissier 
100311fa71b9SJerome Forissier cleanup:
100411fa71b9SJerome Forissier 
100511fa71b9SJerome Forissier     /*
100611fa71b9SJerome Forissier      * This function is also used to import keys. However, wiping the buffers
100711fa71b9SJerome Forissier      * upon failure is not necessary because failure only can happen before any
100811fa71b9SJerome Forissier      * input is copied.
100911fa71b9SJerome Forissier      */
101011fa71b9SJerome Forissier     return( ret );
101111fa71b9SJerome Forissier }
101211fa71b9SJerome Forissier 
101311fa71b9SJerome Forissier /*
1014817466cbSJens Wiklander  * Import X from unsigned binary data, big endian
1015817466cbSJens Wiklander  */
1016817466cbSJens Wiklander int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
1017817466cbSJens Wiklander {
101811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
10193d3b0591SJens Wiklander     size_t const limbs    = CHARS_TO_LIMBS( buflen );
10205b25c76aSJerome Forissier     size_t const overhead = ( limbs * ciL ) - buflen;
10215b25c76aSJerome Forissier     unsigned char *Xp;
1022817466cbSJens Wiklander 
10233d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
10243d3b0591SJens Wiklander     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
1025817466cbSJens Wiklander 
10263d3b0591SJens Wiklander     /* Ensure that target MPI has exactly the necessary number of limbs */
1027*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
10282976273fSJens Wiklander 
1029*7901324dSJerome Forissier     /* Avoid calling `memcpy` with NULL source or destination argument,
10305b25c76aSJerome Forissier      * even if buflen is 0. */
1031*7901324dSJerome Forissier     if( buflen != 0 )
10325b25c76aSJerome Forissier     {
10335b25c76aSJerome Forissier         Xp = (unsigned char*) X->p;
10345b25c76aSJerome Forissier         memcpy( Xp + overhead, buf, buflen );
10355b25c76aSJerome Forissier 
10365b25c76aSJerome Forissier         mpi_bigendian_to_host( X->p, limbs );
10375b25c76aSJerome Forissier     }
1038817466cbSJens Wiklander 
1039817466cbSJens Wiklander cleanup:
1040817466cbSJens Wiklander 
104111fa71b9SJerome Forissier     /*
104211fa71b9SJerome Forissier      * This function is also used to import keys. However, wiping the buffers
104311fa71b9SJerome Forissier      * upon failure is not necessary because failure only can happen before any
104411fa71b9SJerome Forissier      * input is copied.
104511fa71b9SJerome Forissier      */
1046817466cbSJens Wiklander     return( ret );
1047817466cbSJens Wiklander }
1048817466cbSJens Wiklander 
1049817466cbSJens Wiklander /*
105011fa71b9SJerome Forissier  * Export X into unsigned binary data, little endian
105111fa71b9SJerome Forissier  */
105211fa71b9SJerome Forissier int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
105311fa71b9SJerome Forissier                                  unsigned char *buf, size_t buflen )
105411fa71b9SJerome Forissier {
105511fa71b9SJerome Forissier     size_t stored_bytes = X->n * ciL;
105611fa71b9SJerome Forissier     size_t bytes_to_copy;
105711fa71b9SJerome Forissier     size_t i;
105811fa71b9SJerome Forissier 
105911fa71b9SJerome Forissier     if( stored_bytes < buflen )
106011fa71b9SJerome Forissier     {
106111fa71b9SJerome Forissier         bytes_to_copy = stored_bytes;
106211fa71b9SJerome Forissier     }
106311fa71b9SJerome Forissier     else
106411fa71b9SJerome Forissier     {
106511fa71b9SJerome Forissier         bytes_to_copy = buflen;
106611fa71b9SJerome Forissier 
106711fa71b9SJerome Forissier         /* The output buffer is smaller than the allocated size of X.
106811fa71b9SJerome Forissier          * However X may fit if its leading bytes are zero. */
106911fa71b9SJerome Forissier         for( i = bytes_to_copy; i < stored_bytes; i++ )
107011fa71b9SJerome Forissier         {
107111fa71b9SJerome Forissier             if( GET_BYTE( X, i ) != 0 )
107211fa71b9SJerome Forissier                 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
107311fa71b9SJerome Forissier         }
107411fa71b9SJerome Forissier     }
107511fa71b9SJerome Forissier 
107611fa71b9SJerome Forissier     for( i = 0; i < bytes_to_copy; i++ )
107711fa71b9SJerome Forissier         buf[i] = GET_BYTE( X, i );
107811fa71b9SJerome Forissier 
107911fa71b9SJerome Forissier     if( stored_bytes < buflen )
108011fa71b9SJerome Forissier     {
108111fa71b9SJerome Forissier         /* Write trailing 0 bytes */
108211fa71b9SJerome Forissier         memset( buf + stored_bytes, 0, buflen - stored_bytes );
108311fa71b9SJerome Forissier     }
108411fa71b9SJerome Forissier 
108511fa71b9SJerome Forissier     return( 0 );
108611fa71b9SJerome Forissier }
108711fa71b9SJerome Forissier 
108811fa71b9SJerome Forissier /*
1089817466cbSJens Wiklander  * Export X into unsigned binary data, big endian
1090817466cbSJens Wiklander  */
10913d3b0591SJens Wiklander int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
10923d3b0591SJens Wiklander                               unsigned char *buf, size_t buflen )
1093817466cbSJens Wiklander {
10943d3b0591SJens Wiklander     size_t stored_bytes;
10953d3b0591SJens Wiklander     size_t bytes_to_copy;
10963d3b0591SJens Wiklander     unsigned char *p;
10973d3b0591SJens Wiklander     size_t i;
1098817466cbSJens Wiklander 
10993d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
11003d3b0591SJens Wiklander     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
1101817466cbSJens Wiklander 
11023d3b0591SJens Wiklander     stored_bytes = X->n * ciL;
11033d3b0591SJens Wiklander 
11043d3b0591SJens Wiklander     if( stored_bytes < buflen )
11053d3b0591SJens Wiklander     {
11063d3b0591SJens Wiklander         /* There is enough space in the output buffer. Write initial
11073d3b0591SJens Wiklander          * null bytes and record the position at which to start
11083d3b0591SJens Wiklander          * writing the significant bytes. In this case, the execution
11093d3b0591SJens Wiklander          * trace of this function does not depend on the value of the
11103d3b0591SJens Wiklander          * number. */
11113d3b0591SJens Wiklander         bytes_to_copy = stored_bytes;
11123d3b0591SJens Wiklander         p = buf + buflen - stored_bytes;
11133d3b0591SJens Wiklander         memset( buf, 0, buflen - stored_bytes );
11143d3b0591SJens Wiklander     }
11153d3b0591SJens Wiklander     else
11163d3b0591SJens Wiklander     {
11173d3b0591SJens Wiklander         /* The output buffer is smaller than the allocated size of X.
11183d3b0591SJens Wiklander          * However X may fit if its leading bytes are zero. */
11193d3b0591SJens Wiklander         bytes_to_copy = buflen;
11203d3b0591SJens Wiklander         p = buf;
11213d3b0591SJens Wiklander         for( i = bytes_to_copy; i < stored_bytes; i++ )
11223d3b0591SJens Wiklander         {
11233d3b0591SJens Wiklander             if( GET_BYTE( X, i ) != 0 )
1124817466cbSJens Wiklander                 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
11253d3b0591SJens Wiklander         }
11263d3b0591SJens Wiklander     }
1127817466cbSJens Wiklander 
11283d3b0591SJens Wiklander     for( i = 0; i < bytes_to_copy; i++ )
11293d3b0591SJens Wiklander         p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
1130817466cbSJens Wiklander 
1131817466cbSJens Wiklander     return( 0 );
1132817466cbSJens Wiklander }
1133817466cbSJens Wiklander 
1134817466cbSJens Wiklander /*
1135817466cbSJens Wiklander  * Left-shift: X <<= count
1136817466cbSJens Wiklander  */
1137817466cbSJens Wiklander int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
1138817466cbSJens Wiklander {
113911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1140817466cbSJens Wiklander     size_t i, v0, t1;
1141817466cbSJens Wiklander     mbedtls_mpi_uint r0 = 0, r1;
11423d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
1143817466cbSJens Wiklander 
1144817466cbSJens Wiklander     v0 = count / (biL    );
1145817466cbSJens Wiklander     t1 = count & (biL - 1);
1146817466cbSJens Wiklander 
1147817466cbSJens Wiklander     i = mbedtls_mpi_bitlen( X ) + count;
1148817466cbSJens Wiklander 
1149817466cbSJens Wiklander     if( X->n * biL < i )
1150817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
1151817466cbSJens Wiklander 
1152817466cbSJens Wiklander     ret = 0;
1153817466cbSJens Wiklander 
1154817466cbSJens Wiklander     /*
1155817466cbSJens Wiklander      * shift by count / limb_size
1156817466cbSJens Wiklander      */
1157817466cbSJens Wiklander     if( v0 > 0 )
1158817466cbSJens Wiklander     {
1159817466cbSJens Wiklander         for( i = X->n; i > v0; i-- )
1160817466cbSJens Wiklander             X->p[i - 1] = X->p[i - v0 - 1];
1161817466cbSJens Wiklander 
1162817466cbSJens Wiklander         for( ; i > 0; i-- )
1163817466cbSJens Wiklander             X->p[i - 1] = 0;
1164817466cbSJens Wiklander     }
1165817466cbSJens Wiklander 
1166817466cbSJens Wiklander     /*
1167817466cbSJens Wiklander      * shift by count % limb_size
1168817466cbSJens Wiklander      */
1169817466cbSJens Wiklander     if( t1 > 0 )
1170817466cbSJens Wiklander     {
1171817466cbSJens Wiklander         for( i = v0; i < X->n; i++ )
1172817466cbSJens Wiklander         {
1173817466cbSJens Wiklander             r1 = X->p[i] >> (biL - t1);
1174817466cbSJens Wiklander             X->p[i] <<= t1;
1175817466cbSJens Wiklander             X->p[i] |= r0;
1176817466cbSJens Wiklander             r0 = r1;
1177817466cbSJens Wiklander         }
1178817466cbSJens Wiklander     }
1179817466cbSJens Wiklander 
1180817466cbSJens Wiklander cleanup:
1181817466cbSJens Wiklander 
1182817466cbSJens Wiklander     return( ret );
1183817466cbSJens Wiklander }
1184817466cbSJens Wiklander 
1185817466cbSJens Wiklander /*
1186817466cbSJens Wiklander  * Right-shift: X >>= count
1187817466cbSJens Wiklander  */
1188817466cbSJens Wiklander int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
1189817466cbSJens Wiklander {
1190817466cbSJens Wiklander     size_t i, v0, v1;
1191817466cbSJens Wiklander     mbedtls_mpi_uint r0 = 0, r1;
11923d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
1193817466cbSJens Wiklander 
1194817466cbSJens Wiklander     v0 = count /  biL;
1195817466cbSJens Wiklander     v1 = count & (biL - 1);
1196817466cbSJens Wiklander 
1197817466cbSJens Wiklander     if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
1198817466cbSJens Wiklander         return mbedtls_mpi_lset( X, 0 );
1199817466cbSJens Wiklander 
1200817466cbSJens Wiklander     /*
1201817466cbSJens Wiklander      * shift by count / limb_size
1202817466cbSJens Wiklander      */
1203817466cbSJens Wiklander     if( v0 > 0 )
1204817466cbSJens Wiklander     {
1205817466cbSJens Wiklander         for( i = 0; i < X->n - v0; i++ )
1206817466cbSJens Wiklander             X->p[i] = X->p[i + v0];
1207817466cbSJens Wiklander 
1208817466cbSJens Wiklander         for( ; i < X->n; i++ )
1209817466cbSJens Wiklander             X->p[i] = 0;
1210817466cbSJens Wiklander     }
1211817466cbSJens Wiklander 
1212817466cbSJens Wiklander     /*
1213817466cbSJens Wiklander      * shift by count % limb_size
1214817466cbSJens Wiklander      */
1215817466cbSJens Wiklander     if( v1 > 0 )
1216817466cbSJens Wiklander     {
1217817466cbSJens Wiklander         for( i = X->n; i > 0; i-- )
1218817466cbSJens Wiklander         {
1219817466cbSJens Wiklander             r1 = X->p[i - 1] << (biL - v1);
1220817466cbSJens Wiklander             X->p[i - 1] >>= v1;
1221817466cbSJens Wiklander             X->p[i - 1] |= r0;
1222817466cbSJens Wiklander             r0 = r1;
1223817466cbSJens Wiklander         }
1224817466cbSJens Wiklander     }
1225817466cbSJens Wiklander 
1226817466cbSJens Wiklander     return( 0 );
1227817466cbSJens Wiklander }
1228817466cbSJens Wiklander 
1229817466cbSJens Wiklander /*
1230817466cbSJens Wiklander  * Compare unsigned values
1231817466cbSJens Wiklander  */
1232817466cbSJens Wiklander int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
1233817466cbSJens Wiklander {
1234817466cbSJens Wiklander     size_t i, j;
12353d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
12363d3b0591SJens Wiklander     MPI_VALIDATE_RET( Y != NULL );
1237817466cbSJens Wiklander 
1238817466cbSJens Wiklander     for( i = X->n; i > 0; i-- )
1239817466cbSJens Wiklander         if( X->p[i - 1] != 0 )
1240817466cbSJens Wiklander             break;
1241817466cbSJens Wiklander 
1242817466cbSJens Wiklander     for( j = Y->n; j > 0; j-- )
1243817466cbSJens Wiklander         if( Y->p[j - 1] != 0 )
1244817466cbSJens Wiklander             break;
1245817466cbSJens Wiklander 
1246817466cbSJens Wiklander     if( i == 0 && j == 0 )
1247817466cbSJens Wiklander         return( 0 );
1248817466cbSJens Wiklander 
1249817466cbSJens Wiklander     if( i > j ) return(  1 );
1250817466cbSJens Wiklander     if( j > i ) return( -1 );
1251817466cbSJens Wiklander 
1252817466cbSJens Wiklander     for( ; i > 0; i-- )
1253817466cbSJens Wiklander     {
1254817466cbSJens Wiklander         if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
1255817466cbSJens Wiklander         if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
1256817466cbSJens Wiklander     }
1257817466cbSJens Wiklander 
1258817466cbSJens Wiklander     return( 0 );
1259817466cbSJens Wiklander }
1260817466cbSJens Wiklander 
1261817466cbSJens Wiklander /*
1262817466cbSJens Wiklander  * Compare signed values
1263817466cbSJens Wiklander  */
1264817466cbSJens Wiklander int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
1265817466cbSJens Wiklander {
1266817466cbSJens Wiklander     size_t i, j;
12673d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
12683d3b0591SJens Wiklander     MPI_VALIDATE_RET( Y != NULL );
1269817466cbSJens Wiklander 
1270817466cbSJens Wiklander     for( i = X->n; i > 0; i-- )
1271817466cbSJens Wiklander         if( X->p[i - 1] != 0 )
1272817466cbSJens Wiklander             break;
1273817466cbSJens Wiklander 
1274817466cbSJens Wiklander     for( j = Y->n; j > 0; j-- )
1275817466cbSJens Wiklander         if( Y->p[j - 1] != 0 )
1276817466cbSJens Wiklander             break;
1277817466cbSJens Wiklander 
1278817466cbSJens Wiklander     if( i == 0 && j == 0 )
1279817466cbSJens Wiklander         return( 0 );
1280817466cbSJens Wiklander 
1281817466cbSJens Wiklander     if( i > j ) return(  X->s );
1282817466cbSJens Wiklander     if( j > i ) return( -Y->s );
1283817466cbSJens Wiklander 
1284817466cbSJens Wiklander     if( X->s > 0 && Y->s < 0 ) return(  1 );
1285817466cbSJens Wiklander     if( Y->s > 0 && X->s < 0 ) return( -1 );
1286817466cbSJens Wiklander 
1287817466cbSJens Wiklander     for( ; i > 0; i-- )
1288817466cbSJens Wiklander     {
1289817466cbSJens Wiklander         if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
1290817466cbSJens Wiklander         if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
1291817466cbSJens Wiklander     }
1292817466cbSJens Wiklander 
1293817466cbSJens Wiklander     return( 0 );
1294817466cbSJens Wiklander }
1295817466cbSJens Wiklander 
12965b25c76aSJerome Forissier /** Decide if an integer is less than the other, without branches.
12975b25c76aSJerome Forissier  *
12985b25c76aSJerome Forissier  * \param x         First integer.
12995b25c76aSJerome Forissier  * \param y         Second integer.
13005b25c76aSJerome Forissier  *
13015b25c76aSJerome Forissier  * \return          1 if \p x is less than \p y, 0 otherwise
13025b25c76aSJerome Forissier  */
13035b25c76aSJerome Forissier static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
13045b25c76aSJerome Forissier         const mbedtls_mpi_uint y )
13055b25c76aSJerome Forissier {
13065b25c76aSJerome Forissier     mbedtls_mpi_uint ret;
13075b25c76aSJerome Forissier     mbedtls_mpi_uint cond;
13085b25c76aSJerome Forissier 
13095b25c76aSJerome Forissier     /*
13105b25c76aSJerome Forissier      * Check if the most significant bits (MSB) of the operands are different.
13115b25c76aSJerome Forissier      */
13125b25c76aSJerome Forissier     cond = ( x ^ y );
13135b25c76aSJerome Forissier     /*
13145b25c76aSJerome Forissier      * If the MSB are the same then the difference x-y will be negative (and
13155b25c76aSJerome Forissier      * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
13165b25c76aSJerome Forissier      */
13175b25c76aSJerome Forissier     ret = ( x - y ) & ~cond;
13185b25c76aSJerome Forissier     /*
13195b25c76aSJerome Forissier      * If the MSB are different, then the operand with the MSB of 1 is the
13205b25c76aSJerome Forissier      * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
13215b25c76aSJerome Forissier      * the MSB of y is 0.)
13225b25c76aSJerome Forissier      */
13235b25c76aSJerome Forissier     ret |= y & cond;
13245b25c76aSJerome Forissier 
13255b25c76aSJerome Forissier 
13265b25c76aSJerome Forissier     ret = ret >> ( biL - 1 );
13275b25c76aSJerome Forissier 
13285b25c76aSJerome Forissier     return (unsigned) ret;
13295b25c76aSJerome Forissier }
13305b25c76aSJerome Forissier 
13315b25c76aSJerome Forissier /*
13325b25c76aSJerome Forissier  * Compare signed values in constant time
13335b25c76aSJerome Forissier  */
13345b25c76aSJerome Forissier int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
13355b25c76aSJerome Forissier         unsigned *ret )
13365b25c76aSJerome Forissier {
13375b25c76aSJerome Forissier     size_t i;
13385b25c76aSJerome Forissier     /* The value of any of these variables is either 0 or 1 at all times. */
13395b25c76aSJerome Forissier     unsigned cond, done, X_is_negative, Y_is_negative;
13405b25c76aSJerome Forissier 
13415b25c76aSJerome Forissier     MPI_VALIDATE_RET( X != NULL );
13425b25c76aSJerome Forissier     MPI_VALIDATE_RET( Y != NULL );
13435b25c76aSJerome Forissier     MPI_VALIDATE_RET( ret != NULL );
13445b25c76aSJerome Forissier 
13455b25c76aSJerome Forissier     if( X->n != Y->n )
13465b25c76aSJerome Forissier         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
13475b25c76aSJerome Forissier 
13485b25c76aSJerome Forissier     /*
13495b25c76aSJerome Forissier      * Set sign_N to 1 if N >= 0, 0 if N < 0.
13505b25c76aSJerome Forissier      * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
13515b25c76aSJerome Forissier      */
13525b25c76aSJerome Forissier     X_is_negative = ( X->s & 2 ) >> 1;
13535b25c76aSJerome Forissier     Y_is_negative = ( Y->s & 2 ) >> 1;
13545b25c76aSJerome Forissier 
13555b25c76aSJerome Forissier     /*
13565b25c76aSJerome Forissier      * If the signs are different, then the positive operand is the bigger.
13575b25c76aSJerome Forissier      * That is if X is negative (X_is_negative == 1), then X < Y is true and it
13585b25c76aSJerome Forissier      * is false if X is positive (X_is_negative == 0).
13595b25c76aSJerome Forissier      */
13605b25c76aSJerome Forissier     cond = ( X_is_negative ^ Y_is_negative );
13615b25c76aSJerome Forissier     *ret = cond & X_is_negative;
13625b25c76aSJerome Forissier 
13635b25c76aSJerome Forissier     /*
13645b25c76aSJerome Forissier      * This is a constant-time function. We might have the result, but we still
13655b25c76aSJerome Forissier      * need to go through the loop. Record if we have the result already.
13665b25c76aSJerome Forissier      */
13675b25c76aSJerome Forissier     done = cond;
13685b25c76aSJerome Forissier 
13695b25c76aSJerome Forissier     for( i = X->n; i > 0; i-- )
13705b25c76aSJerome Forissier     {
13715b25c76aSJerome Forissier         /*
13725b25c76aSJerome Forissier          * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
13735b25c76aSJerome Forissier          * X and Y are negative.
13745b25c76aSJerome Forissier          *
13755b25c76aSJerome Forissier          * Again even if we can make a decision, we just mark the result and
13765b25c76aSJerome Forissier          * the fact that we are done and continue looping.
13775b25c76aSJerome Forissier          */
13785b25c76aSJerome Forissier         cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
13795b25c76aSJerome Forissier         *ret |= cond & ( 1 - done ) & X_is_negative;
13805b25c76aSJerome Forissier         done |= cond;
13815b25c76aSJerome Forissier 
13825b25c76aSJerome Forissier         /*
13835b25c76aSJerome Forissier          * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
13845b25c76aSJerome Forissier          * X and Y are positive.
13855b25c76aSJerome Forissier          *
13865b25c76aSJerome Forissier          * Again even if we can make a decision, we just mark the result and
13875b25c76aSJerome Forissier          * the fact that we are done and continue looping.
13885b25c76aSJerome Forissier          */
13895b25c76aSJerome Forissier         cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
13905b25c76aSJerome Forissier         *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
13915b25c76aSJerome Forissier         done |= cond;
13925b25c76aSJerome Forissier     }
13935b25c76aSJerome Forissier 
13945b25c76aSJerome Forissier     return( 0 );
13955b25c76aSJerome Forissier }
13965b25c76aSJerome Forissier 
1397817466cbSJens Wiklander /*
1398817466cbSJens Wiklander  * Compare signed values
1399817466cbSJens Wiklander  */
1400817466cbSJens Wiklander int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
1401817466cbSJens Wiklander {
1402817466cbSJens Wiklander     mbedtls_mpi Y;
1403817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
14043d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
1405817466cbSJens Wiklander 
1406817466cbSJens Wiklander     *p  = ( z < 0 ) ? -z : z;
1407817466cbSJens Wiklander     Y.s = ( z < 0 ) ? -1 : 1;
1408817466cbSJens Wiklander     Y.n = 1;
1409817466cbSJens Wiklander     Y.p = p;
1410817466cbSJens Wiklander 
1411817466cbSJens Wiklander     return( mbedtls_mpi_cmp_mpi( X, &Y ) );
1412817466cbSJens Wiklander }
1413817466cbSJens Wiklander 
1414817466cbSJens Wiklander /*
1415817466cbSJens Wiklander  * Unsigned addition: X = |A| + |B|  (HAC 14.7)
1416817466cbSJens Wiklander  */
1417817466cbSJens Wiklander int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1418817466cbSJens Wiklander {
141911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1420817466cbSJens Wiklander     size_t i, j;
1421817466cbSJens Wiklander     mbedtls_mpi_uint *o, *p, c, tmp;
14223d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
14233d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
14243d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1425817466cbSJens Wiklander 
1426817466cbSJens Wiklander     if( X == B )
1427817466cbSJens Wiklander     {
1428817466cbSJens Wiklander         const mbedtls_mpi *T = A; A = X; B = T;
1429817466cbSJens Wiklander     }
1430817466cbSJens Wiklander 
1431817466cbSJens Wiklander     if( X != A )
1432817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1433817466cbSJens Wiklander 
1434817466cbSJens Wiklander     /*
1435817466cbSJens Wiklander      * X should always be positive as a result of unsigned additions.
1436817466cbSJens Wiklander      */
1437817466cbSJens Wiklander     X->s = 1;
1438817466cbSJens Wiklander 
1439817466cbSJens Wiklander     for( j = B->n; j > 0; j-- )
1440817466cbSJens Wiklander         if( B->p[j - 1] != 0 )
1441817466cbSJens Wiklander             break;
1442817466cbSJens Wiklander 
1443817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1444817466cbSJens Wiklander 
1445817466cbSJens Wiklander     o = B->p; p = X->p; c = 0;
1446817466cbSJens Wiklander 
1447817466cbSJens Wiklander     /*
1448817466cbSJens Wiklander      * tmp is used because it might happen that p == o
1449817466cbSJens Wiklander      */
1450817466cbSJens Wiklander     for( i = 0; i < j; i++, o++, p++ )
1451817466cbSJens Wiklander     {
1452817466cbSJens Wiklander         tmp= *o;
1453817466cbSJens Wiklander         *p +=  c; c  = ( *p <  c );
1454817466cbSJens Wiklander         *p += tmp; c += ( *p < tmp );
1455817466cbSJens Wiklander     }
1456817466cbSJens Wiklander 
1457817466cbSJens Wiklander     while( c != 0 )
1458817466cbSJens Wiklander     {
1459817466cbSJens Wiklander         if( i >= X->n )
1460817466cbSJens Wiklander         {
1461817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
1462817466cbSJens Wiklander             p = X->p + i;
1463817466cbSJens Wiklander         }
1464817466cbSJens Wiklander 
1465817466cbSJens Wiklander         *p += c; c = ( *p < c ); i++; p++;
1466817466cbSJens Wiklander     }
1467817466cbSJens Wiklander 
1468817466cbSJens Wiklander cleanup:
1469817466cbSJens Wiklander 
1470817466cbSJens Wiklander     return( ret );
1471817466cbSJens Wiklander }
1472817466cbSJens Wiklander 
1473*7901324dSJerome Forissier /**
1474*7901324dSJerome Forissier  * Helper for mbedtls_mpi subtraction.
1475*7901324dSJerome Forissier  *
1476*7901324dSJerome Forissier  * Calculate l - r where l and r have the same size.
1477*7901324dSJerome Forissier  * This function operates modulo (2^ciL)^n and returns the carry
1478*7901324dSJerome Forissier  * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
1479*7901324dSJerome Forissier  *
1480*7901324dSJerome Forissier  * d may be aliased to l or r.
1481*7901324dSJerome Forissier  *
1482*7901324dSJerome Forissier  * \param n             Number of limbs of \p d, \p l and \p r.
1483*7901324dSJerome Forissier  * \param[out] d        The result of the subtraction.
1484*7901324dSJerome Forissier  * \param[in] l         The left operand.
1485*7901324dSJerome Forissier  * \param[in] r         The right operand.
1486*7901324dSJerome Forissier  *
1487*7901324dSJerome Forissier  * \return              1 if `l < r`.
1488*7901324dSJerome Forissier  *                      0 if `l >= r`.
1489817466cbSJens Wiklander  */
1490*7901324dSJerome Forissier static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
1491*7901324dSJerome Forissier                                      mbedtls_mpi_uint *d,
1492*7901324dSJerome Forissier                                      const mbedtls_mpi_uint *l,
1493*7901324dSJerome Forissier                                      const mbedtls_mpi_uint *r )
1494817466cbSJens Wiklander {
1495817466cbSJens Wiklander     size_t i;
1496*7901324dSJerome Forissier     mbedtls_mpi_uint c = 0, t, z;
1497817466cbSJens Wiklander 
1498*7901324dSJerome Forissier     for( i = 0; i < n; i++ )
1499817466cbSJens Wiklander     {
1500*7901324dSJerome Forissier         z = ( l[i] <  c );    t = l[i] - c;
1501*7901324dSJerome Forissier         c = ( t < r[i] ) + z; d[i] = t - r[i];
1502817466cbSJens Wiklander     }
1503817466cbSJens Wiklander 
1504*7901324dSJerome Forissier     return( c );
1505817466cbSJens Wiklander }
1506817466cbSJens Wiklander 
1507817466cbSJens Wiklander /*
1508*7901324dSJerome Forissier  * Unsigned subtraction: X = |A| - |B|  (HAC 14.9, 14.10)
1509817466cbSJens Wiklander  */
1510817466cbSJens Wiklander int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1511817466cbSJens Wiklander {
151211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1513817466cbSJens Wiklander     size_t n;
1514*7901324dSJerome Forissier     mbedtls_mpi_uint carry;
15153d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
15163d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
15173d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1518817466cbSJens Wiklander 
1519817466cbSJens Wiklander     for( n = B->n; n > 0; n-- )
1520817466cbSJens Wiklander         if( B->p[n - 1] != 0 )
1521817466cbSJens Wiklander             break;
1522*7901324dSJerome Forissier     if( n > A->n )
1523*7901324dSJerome Forissier     {
1524*7901324dSJerome Forissier         /* B >= (2^ciL)^n > A */
1525*7901324dSJerome Forissier         ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1526*7901324dSJerome Forissier         goto cleanup;
1527*7901324dSJerome Forissier     }
1528817466cbSJens Wiklander 
1529*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
1530*7901324dSJerome Forissier 
1531*7901324dSJerome Forissier     /* Set the high limbs of X to match A. Don't touch the lower limbs
1532*7901324dSJerome Forissier      * because X might be aliased to B, and we must not overwrite the
1533*7901324dSJerome Forissier      * significant digits of B. */
1534*7901324dSJerome Forissier     if( A->n > n )
1535*7901324dSJerome Forissier         memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
1536*7901324dSJerome Forissier     if( X->n > A->n )
1537*7901324dSJerome Forissier         memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
1538*7901324dSJerome Forissier 
1539*7901324dSJerome Forissier     carry = mpi_sub_hlp( n, X->p, A->p, B->p );
1540*7901324dSJerome Forissier     if( carry != 0 )
1541*7901324dSJerome Forissier     {
1542*7901324dSJerome Forissier         /* Propagate the carry to the first nonzero limb of X. */
1543*7901324dSJerome Forissier         for( ; n < X->n && X->p[n] == 0; n++ )
1544*7901324dSJerome Forissier             --X->p[n];
1545*7901324dSJerome Forissier         /* If we ran out of space for the carry, it means that the result
1546*7901324dSJerome Forissier          * is negative. */
1547*7901324dSJerome Forissier         if( n == X->n )
1548*7901324dSJerome Forissier         {
1549*7901324dSJerome Forissier             ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
1550*7901324dSJerome Forissier             goto cleanup;
1551*7901324dSJerome Forissier         }
1552*7901324dSJerome Forissier         --X->p[n];
1553*7901324dSJerome Forissier     }
1554*7901324dSJerome Forissier 
1555*7901324dSJerome Forissier     /* X should always be positive as a result of unsigned subtractions. */
1556*7901324dSJerome Forissier     X->s = 1;
1557817466cbSJens Wiklander 
1558817466cbSJens Wiklander cleanup:
1559817466cbSJens Wiklander     return( ret );
1560817466cbSJens Wiklander }
1561817466cbSJens Wiklander 
1562817466cbSJens Wiklander /*
1563817466cbSJens Wiklander  * Signed addition: X = A + B
1564817466cbSJens Wiklander  */
1565817466cbSJens Wiklander int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1566817466cbSJens Wiklander {
15673d3b0591SJens Wiklander     int ret, s;
15683d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
15693d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
15703d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1571817466cbSJens Wiklander 
15723d3b0591SJens Wiklander     s = A->s;
1573817466cbSJens Wiklander     if( A->s * B->s < 0 )
1574817466cbSJens Wiklander     {
1575817466cbSJens Wiklander         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1576817466cbSJens Wiklander         {
1577817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1578817466cbSJens Wiklander             X->s =  s;
1579817466cbSJens Wiklander         }
1580817466cbSJens Wiklander         else
1581817466cbSJens Wiklander         {
1582817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1583817466cbSJens Wiklander             X->s = -s;
1584817466cbSJens Wiklander         }
1585817466cbSJens Wiklander     }
1586817466cbSJens Wiklander     else
1587817466cbSJens Wiklander     {
1588817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1589817466cbSJens Wiklander         X->s = s;
1590817466cbSJens Wiklander     }
1591817466cbSJens Wiklander 
1592817466cbSJens Wiklander cleanup:
1593817466cbSJens Wiklander 
1594817466cbSJens Wiklander     return( ret );
1595817466cbSJens Wiklander }
1596817466cbSJens Wiklander 
1597817466cbSJens Wiklander /*
1598817466cbSJens Wiklander  * Signed subtraction: X = A - B
1599817466cbSJens Wiklander  */
1600817466cbSJens Wiklander int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1601817466cbSJens Wiklander {
16023d3b0591SJens Wiklander     int ret, s;
16033d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
16043d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
16053d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1606817466cbSJens Wiklander 
16073d3b0591SJens Wiklander     s = A->s;
1608817466cbSJens Wiklander     if( A->s * B->s > 0 )
1609817466cbSJens Wiklander     {
1610817466cbSJens Wiklander         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1611817466cbSJens Wiklander         {
1612817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1613817466cbSJens Wiklander             X->s =  s;
1614817466cbSJens Wiklander         }
1615817466cbSJens Wiklander         else
1616817466cbSJens Wiklander         {
1617817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1618817466cbSJens Wiklander             X->s = -s;
1619817466cbSJens Wiklander         }
1620817466cbSJens Wiklander     }
1621817466cbSJens Wiklander     else
1622817466cbSJens Wiklander     {
1623817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1624817466cbSJens Wiklander         X->s = s;
1625817466cbSJens Wiklander     }
1626817466cbSJens Wiklander 
1627817466cbSJens Wiklander cleanup:
1628817466cbSJens Wiklander 
1629817466cbSJens Wiklander     return( ret );
1630817466cbSJens Wiklander }
1631817466cbSJens Wiklander 
1632817466cbSJens Wiklander /*
1633817466cbSJens Wiklander  * Signed addition: X = A + b
1634817466cbSJens Wiklander  */
1635817466cbSJens Wiklander int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1636817466cbSJens Wiklander {
1637817466cbSJens Wiklander     mbedtls_mpi _B;
1638817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
16393d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
16403d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
1641817466cbSJens Wiklander 
1642817466cbSJens Wiklander     p[0] = ( b < 0 ) ? -b : b;
1643817466cbSJens Wiklander     _B.s = ( b < 0 ) ? -1 : 1;
1644817466cbSJens Wiklander     _B.n = 1;
1645817466cbSJens Wiklander     _B.p = p;
1646817466cbSJens Wiklander 
1647817466cbSJens Wiklander     return( mbedtls_mpi_add_mpi( X, A, &_B ) );
1648817466cbSJens Wiklander }
1649817466cbSJens Wiklander 
1650817466cbSJens Wiklander /*
1651817466cbSJens Wiklander  * Signed subtraction: X = A - b
1652817466cbSJens Wiklander  */
1653817466cbSJens Wiklander int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1654817466cbSJens Wiklander {
1655817466cbSJens Wiklander     mbedtls_mpi _B;
1656817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
16573d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
16583d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
1659817466cbSJens Wiklander 
1660817466cbSJens Wiklander     p[0] = ( b < 0 ) ? -b : b;
1661817466cbSJens Wiklander     _B.s = ( b < 0 ) ? -1 : 1;
1662817466cbSJens Wiklander     _B.n = 1;
1663817466cbSJens Wiklander     _B.p = p;
1664817466cbSJens Wiklander 
1665817466cbSJens Wiklander     return( mbedtls_mpi_sub_mpi( X, A, &_B ) );
1666817466cbSJens Wiklander }
1667817466cbSJens Wiklander 
1668*7901324dSJerome Forissier /** Helper for mbedtls_mpi multiplication.
1669*7901324dSJerome Forissier  *
1670*7901324dSJerome Forissier  * Add \p b * \p s to \p d.
1671*7901324dSJerome Forissier  *
1672*7901324dSJerome Forissier  * \param i             The number of limbs of \p s.
1673*7901324dSJerome Forissier  * \param[in] s         A bignum to multiply, of size \p i.
1674*7901324dSJerome Forissier  *                      It may overlap with \p d, but only if
1675*7901324dSJerome Forissier  *                      \p d <= \p s.
1676*7901324dSJerome Forissier  *                      Its leading limb must not be \c 0.
1677*7901324dSJerome Forissier  * \param[in,out] d     The bignum to add to.
1678*7901324dSJerome Forissier  *                      It must be sufficiently large to store the
1679*7901324dSJerome Forissier  *                      result of the multiplication. This means
1680*7901324dSJerome Forissier  *                      \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
1681*7901324dSJerome Forissier  *                      is not known a priori.
1682*7901324dSJerome Forissier  * \param b             A scalar to multiply.
1683817466cbSJens Wiklander  */
1684817466cbSJens Wiklander static
1685817466cbSJens Wiklander #if defined(__APPLE__) && defined(__arm__)
1686817466cbSJens Wiklander /*
1687817466cbSJens Wiklander  * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1688817466cbSJens Wiklander  * appears to need this to prevent bad ARM code generation at -O3.
1689817466cbSJens Wiklander  */
1690817466cbSJens Wiklander __attribute__ ((noinline))
1691817466cbSJens Wiklander #endif
1692*7901324dSJerome Forissier void mpi_mul_hlp( size_t i,
1693*7901324dSJerome Forissier                   const mbedtls_mpi_uint *s,
1694*7901324dSJerome Forissier                   mbedtls_mpi_uint *d,
1695*7901324dSJerome Forissier                   mbedtls_mpi_uint b )
1696817466cbSJens Wiklander {
1697817466cbSJens Wiklander     mbedtls_mpi_uint c = 0, t = 0;
1698817466cbSJens Wiklander 
1699817466cbSJens Wiklander #if defined(MULADDC_HUIT)
1700817466cbSJens Wiklander     for( ; i >= 8; i -= 8 )
1701817466cbSJens Wiklander     {
1702817466cbSJens Wiklander         MULADDC_INIT
1703817466cbSJens Wiklander         MULADDC_HUIT
1704817466cbSJens Wiklander         MULADDC_STOP
1705817466cbSJens Wiklander     }
1706817466cbSJens Wiklander 
1707817466cbSJens Wiklander     for( ; i > 0; i-- )
1708817466cbSJens Wiklander     {
1709817466cbSJens Wiklander         MULADDC_INIT
1710817466cbSJens Wiklander         MULADDC_CORE
1711817466cbSJens Wiklander         MULADDC_STOP
1712817466cbSJens Wiklander     }
1713817466cbSJens Wiklander #else /* MULADDC_HUIT */
1714817466cbSJens Wiklander     for( ; i >= 16; i -= 16 )
1715817466cbSJens Wiklander     {
1716817466cbSJens Wiklander         MULADDC_INIT
1717817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1718817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1719817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1720817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1721817466cbSJens Wiklander 
1722817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1723817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1724817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1725817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1726817466cbSJens Wiklander         MULADDC_STOP
1727817466cbSJens Wiklander     }
1728817466cbSJens Wiklander 
1729817466cbSJens Wiklander     for( ; i >= 8; i -= 8 )
1730817466cbSJens Wiklander     {
1731817466cbSJens Wiklander         MULADDC_INIT
1732817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1733817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1734817466cbSJens Wiklander 
1735817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1736817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1737817466cbSJens Wiklander         MULADDC_STOP
1738817466cbSJens Wiklander     }
1739817466cbSJens Wiklander 
1740817466cbSJens Wiklander     for( ; i > 0; i-- )
1741817466cbSJens Wiklander     {
1742817466cbSJens Wiklander         MULADDC_INIT
1743817466cbSJens Wiklander         MULADDC_CORE
1744817466cbSJens Wiklander         MULADDC_STOP
1745817466cbSJens Wiklander     }
1746817466cbSJens Wiklander #endif /* MULADDC_HUIT */
1747817466cbSJens Wiklander 
1748817466cbSJens Wiklander     t++;
1749817466cbSJens Wiklander 
1750*7901324dSJerome Forissier     while( c != 0 )
1751*7901324dSJerome Forissier     {
1752817466cbSJens Wiklander         *d += c; c = ( *d < c ); d++;
1753817466cbSJens Wiklander     }
1754817466cbSJens Wiklander }
1755817466cbSJens Wiklander 
1756817466cbSJens Wiklander /*
1757817466cbSJens Wiklander  * Baseline multiplication: X = A * B  (HAC 14.12)
1758817466cbSJens Wiklander  */
1759817466cbSJens Wiklander int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1760817466cbSJens Wiklander {
176111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1762817466cbSJens Wiklander     size_t i, j;
1763817466cbSJens Wiklander     mbedtls_mpi TA, TB;
1764*7901324dSJerome Forissier     int result_is_zero = 0;
17653d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
17663d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
17673d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1768817466cbSJens Wiklander 
176998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB );
1770817466cbSJens Wiklander 
1771817466cbSJens Wiklander     if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1772817466cbSJens Wiklander     if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
1773817466cbSJens Wiklander 
1774817466cbSJens Wiklander     for( i = A->n; i > 0; i-- )
1775817466cbSJens Wiklander         if( A->p[i - 1] != 0 )
1776817466cbSJens Wiklander             break;
1777*7901324dSJerome Forissier     if( i == 0 )
1778*7901324dSJerome Forissier         result_is_zero = 1;
1779817466cbSJens Wiklander 
1780817466cbSJens Wiklander     for( j = B->n; j > 0; j-- )
1781817466cbSJens Wiklander         if( B->p[j - 1] != 0 )
1782817466cbSJens Wiklander             break;
1783*7901324dSJerome Forissier     if( j == 0 )
1784*7901324dSJerome Forissier         result_is_zero = 1;
1785817466cbSJens Wiklander 
1786817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1787817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
1788817466cbSJens Wiklander 
17893d3b0591SJens Wiklander     for( ; j > 0; j-- )
17903d3b0591SJens Wiklander         mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
1791817466cbSJens Wiklander 
1792*7901324dSJerome Forissier     /* If the result is 0, we don't shortcut the operation, which reduces
1793*7901324dSJerome Forissier      * but does not eliminate side channels leaking the zero-ness. We do
1794*7901324dSJerome Forissier      * need to take care to set the sign bit properly since the library does
1795*7901324dSJerome Forissier      * not fully support an MPI object with a value of 0 and s == -1. */
1796*7901324dSJerome Forissier     if( result_is_zero )
1797*7901324dSJerome Forissier         X->s = 1;
1798*7901324dSJerome Forissier     else
1799817466cbSJens Wiklander         X->s = A->s * B->s;
1800817466cbSJens Wiklander 
1801817466cbSJens Wiklander cleanup:
1802817466cbSJens Wiklander 
1803817466cbSJens Wiklander     mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
1804817466cbSJens Wiklander 
1805817466cbSJens Wiklander     return( ret );
1806817466cbSJens Wiklander }
1807817466cbSJens Wiklander 
1808817466cbSJens Wiklander /*
1809817466cbSJens Wiklander  * Baseline multiplication: X = A * b
1810817466cbSJens Wiklander  */
1811817466cbSJens Wiklander int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
1812817466cbSJens Wiklander {
18133d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
18143d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
1815817466cbSJens Wiklander 
1816*7901324dSJerome Forissier     /* mpi_mul_hlp can't deal with a leading 0. */
1817*7901324dSJerome Forissier     size_t n = A->n;
1818*7901324dSJerome Forissier     while( n > 0 && A->p[n - 1] == 0 )
1819*7901324dSJerome Forissier         --n;
1820817466cbSJens Wiklander 
1821*7901324dSJerome Forissier     /* The general method below doesn't work if n==0 or b==0. By chance
1822*7901324dSJerome Forissier      * calculating the result is trivial in those cases. */
1823*7901324dSJerome Forissier     if( b == 0 || n == 0 )
1824*7901324dSJerome Forissier     {
1825*7901324dSJerome Forissier         return( mbedtls_mpi_lset( X, 0 ) );
1826*7901324dSJerome Forissier     }
1827*7901324dSJerome Forissier 
1828*7901324dSJerome Forissier     /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
1829*7901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1830*7901324dSJerome Forissier     /* In general, A * b requires 1 limb more than b. If
1831*7901324dSJerome Forissier      * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
1832*7901324dSJerome Forissier      * number of limbs as A and the call to grow() is not required since
1833*7901324dSJerome Forissier      * copy() will take care of the growth if needed. However, experimentally,
1834*7901324dSJerome Forissier      * making the call to grow() unconditional causes slightly fewer
1835*7901324dSJerome Forissier      * calls to calloc() in ECP code, presumably because it reuses the
1836*7901324dSJerome Forissier      * same mpi for a while and this way the mpi is more likely to directly
1837*7901324dSJerome Forissier      * grow to its final size. */
1838*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
1839*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1840*7901324dSJerome Forissier     mpi_mul_hlp( n, A->p, X->p, b - 1 );
1841*7901324dSJerome Forissier 
1842*7901324dSJerome Forissier cleanup:
1843*7901324dSJerome Forissier     return( ret );
1844817466cbSJens Wiklander }
1845817466cbSJens Wiklander 
1846817466cbSJens Wiklander /*
1847817466cbSJens Wiklander  * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1848817466cbSJens Wiklander  * mbedtls_mpi_uint divisor, d
1849817466cbSJens Wiklander  */
1850817466cbSJens Wiklander static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1851817466cbSJens Wiklander             mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
1852817466cbSJens Wiklander {
1853817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL)
1854817466cbSJens Wiklander     mbedtls_t_udbl dividend, quotient;
1855817466cbSJens Wiklander #else
1856817466cbSJens Wiklander     const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1857817466cbSJens Wiklander     const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
1858817466cbSJens Wiklander     mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1859817466cbSJens Wiklander     mbedtls_mpi_uint u0_msw, u0_lsw;
1860817466cbSJens Wiklander     size_t s;
1861817466cbSJens Wiklander #endif
1862817466cbSJens Wiklander 
1863817466cbSJens Wiklander     /*
1864817466cbSJens Wiklander      * Check for overflow
1865817466cbSJens Wiklander      */
1866817466cbSJens Wiklander     if( 0 == d || u1 >= d )
1867817466cbSJens Wiklander     {
1868817466cbSJens Wiklander         if (r != NULL) *r = ~0;
1869817466cbSJens Wiklander 
1870817466cbSJens Wiklander         return ( ~0 );
1871817466cbSJens Wiklander     }
1872817466cbSJens Wiklander 
1873817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL)
1874817466cbSJens Wiklander     dividend  = (mbedtls_t_udbl) u1 << biL;
1875817466cbSJens Wiklander     dividend |= (mbedtls_t_udbl) u0;
1876817466cbSJens Wiklander     quotient = dividend / d;
1877817466cbSJens Wiklander     if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1878817466cbSJens Wiklander         quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1879817466cbSJens Wiklander 
1880817466cbSJens Wiklander     if( r != NULL )
1881817466cbSJens Wiklander         *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
1882817466cbSJens Wiklander 
1883817466cbSJens Wiklander     return (mbedtls_mpi_uint) quotient;
1884817466cbSJens Wiklander #else
1885817466cbSJens Wiklander 
1886817466cbSJens Wiklander     /*
1887817466cbSJens Wiklander      * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1888817466cbSJens Wiklander      *   Vol. 2 - Seminumerical Algorithms, Knuth
1889817466cbSJens Wiklander      */
1890817466cbSJens Wiklander 
1891817466cbSJens Wiklander     /*
1892817466cbSJens Wiklander      * Normalize the divisor, d, and dividend, u0, u1
1893817466cbSJens Wiklander      */
1894817466cbSJens Wiklander     s = mbedtls_clz( d );
1895817466cbSJens Wiklander     d = d << s;
1896817466cbSJens Wiklander 
1897817466cbSJens Wiklander     u1 = u1 << s;
1898817466cbSJens Wiklander     u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
1899817466cbSJens Wiklander     u0 =  u0 << s;
1900817466cbSJens Wiklander 
1901817466cbSJens Wiklander     d1 = d >> biH;
1902817466cbSJens Wiklander     d0 = d & uint_halfword_mask;
1903817466cbSJens Wiklander 
1904817466cbSJens Wiklander     u0_msw = u0 >> biH;
1905817466cbSJens Wiklander     u0_lsw = u0 & uint_halfword_mask;
1906817466cbSJens Wiklander 
1907817466cbSJens Wiklander     /*
1908817466cbSJens Wiklander      * Find the first quotient and remainder
1909817466cbSJens Wiklander      */
1910817466cbSJens Wiklander     q1 = u1 / d1;
1911817466cbSJens Wiklander     r0 = u1 - d1 * q1;
1912817466cbSJens Wiklander 
1913817466cbSJens Wiklander     while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1914817466cbSJens Wiklander     {
1915817466cbSJens Wiklander         q1 -= 1;
1916817466cbSJens Wiklander         r0 += d1;
1917817466cbSJens Wiklander 
1918817466cbSJens Wiklander         if ( r0 >= radix ) break;
1919817466cbSJens Wiklander     }
1920817466cbSJens Wiklander 
1921817466cbSJens Wiklander     rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
1922817466cbSJens Wiklander     q0 = rAX / d1;
1923817466cbSJens Wiklander     r0 = rAX - q0 * d1;
1924817466cbSJens Wiklander 
1925817466cbSJens Wiklander     while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1926817466cbSJens Wiklander     {
1927817466cbSJens Wiklander         q0 -= 1;
1928817466cbSJens Wiklander         r0 += d1;
1929817466cbSJens Wiklander 
1930817466cbSJens Wiklander         if ( r0 >= radix ) break;
1931817466cbSJens Wiklander     }
1932817466cbSJens Wiklander 
1933817466cbSJens Wiklander     if (r != NULL)
1934817466cbSJens Wiklander         *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
1935817466cbSJens Wiklander 
1936817466cbSJens Wiklander     quotient = q1 * radix + q0;
1937817466cbSJens Wiklander 
1938817466cbSJens Wiklander     return quotient;
1939817466cbSJens Wiklander #endif
1940817466cbSJens Wiklander }
1941817466cbSJens Wiklander 
1942817466cbSJens Wiklander /*
1943817466cbSJens Wiklander  * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
1944817466cbSJens Wiklander  */
19453d3b0591SJens Wiklander int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
19463d3b0591SJens Wiklander                          const mbedtls_mpi *B )
1947817466cbSJens Wiklander {
194811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1949817466cbSJens Wiklander     size_t i, n, t, k;
1950817466cbSJens Wiklander     mbedtls_mpi X, Y, Z, T1, T2;
195111fa71b9SJerome Forissier     mbedtls_mpi_uint TP2[3];
19523d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
19533d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1954817466cbSJens Wiklander 
1955817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1956817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1957817466cbSJens Wiklander 
195898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &X ); mbedtls_mpi_init_mempool( &Y );
195998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &Z ); mbedtls_mpi_init_mempool( &T1 );
196011fa71b9SJerome Forissier     /*
196111fa71b9SJerome Forissier      * Avoid dynamic memory allocations for constant-size T2.
196211fa71b9SJerome Forissier      *
196311fa71b9SJerome Forissier      * T2 is used for comparison only and the 3 limbs are assigned explicitly,
196411fa71b9SJerome Forissier      * so nobody increase the size of the MPI and we're safe to use an on-stack
196511fa71b9SJerome Forissier      * buffer.
196611fa71b9SJerome Forissier      */
196711fa71b9SJerome Forissier     T2.s = 1;
196811fa71b9SJerome Forissier     T2.n = sizeof( TP2 ) / sizeof( *TP2 );
196911fa71b9SJerome Forissier     T2.p = TP2;
1970817466cbSJens Wiklander 
1971817466cbSJens Wiklander     if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1972817466cbSJens Wiklander     {
1973817466cbSJens Wiklander         if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1974817466cbSJens Wiklander         if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
1975817466cbSJens Wiklander         return( 0 );
1976817466cbSJens Wiklander     }
1977817466cbSJens Wiklander 
1978817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1979817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
1980817466cbSJens Wiklander     X.s = Y.s = 1;
1981817466cbSJens Wiklander 
1982817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1983817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z,  0 ) );
1984*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
1985817466cbSJens Wiklander 
1986817466cbSJens Wiklander     k = mbedtls_mpi_bitlen( &Y ) % biL;
1987817466cbSJens Wiklander     if( k < biL - 1 )
1988817466cbSJens Wiklander     {
1989817466cbSJens Wiklander         k = biL - 1 - k;
1990817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1991817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
1992817466cbSJens Wiklander     }
1993817466cbSJens Wiklander     else k = 0;
1994817466cbSJens Wiklander 
1995817466cbSJens Wiklander     n = X.n - 1;
1996817466cbSJens Wiklander     t = Y.n - 1;
1997817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
1998817466cbSJens Wiklander 
1999817466cbSJens Wiklander     while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
2000817466cbSJens Wiklander     {
2001817466cbSJens Wiklander         Z.p[n - t]++;
2002817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
2003817466cbSJens Wiklander     }
2004817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
2005817466cbSJens Wiklander 
2006817466cbSJens Wiklander     for( i = n; i > t ; i-- )
2007817466cbSJens Wiklander     {
2008817466cbSJens Wiklander         if( X.p[i] >= Y.p[t] )
2009817466cbSJens Wiklander             Z.p[i - t - 1] = ~0;
2010817466cbSJens Wiklander         else
2011817466cbSJens Wiklander         {
2012817466cbSJens Wiklander             Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
2013817466cbSJens Wiklander                                                             Y.p[t], NULL);
2014817466cbSJens Wiklander         }
2015817466cbSJens Wiklander 
201611fa71b9SJerome Forissier         T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
201711fa71b9SJerome Forissier         T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
201811fa71b9SJerome Forissier         T2.p[2] = X.p[i];
201911fa71b9SJerome Forissier 
2020817466cbSJens Wiklander         Z.p[i - t - 1]++;
2021817466cbSJens Wiklander         do
2022817466cbSJens Wiklander         {
2023817466cbSJens Wiklander             Z.p[i - t - 1]--;
2024817466cbSJens Wiklander 
2025817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
2026817466cbSJens Wiklander             T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
2027817466cbSJens Wiklander             T1.p[1] = Y.p[t];
2028817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
2029817466cbSJens Wiklander         }
2030817466cbSJens Wiklander         while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
2031817466cbSJens Wiklander 
2032817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
2033817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1,  biL * ( i - t - 1 ) ) );
2034817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
2035817466cbSJens Wiklander 
2036817466cbSJens Wiklander         if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
2037817466cbSJens Wiklander         {
2038817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
2039817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
2040817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
2041817466cbSJens Wiklander             Z.p[i - t - 1]--;
2042817466cbSJens Wiklander         }
2043817466cbSJens Wiklander     }
2044817466cbSJens Wiklander 
2045817466cbSJens Wiklander     if( Q != NULL )
2046817466cbSJens Wiklander     {
2047817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
2048817466cbSJens Wiklander         Q->s = A->s * B->s;
2049817466cbSJens Wiklander     }
2050817466cbSJens Wiklander 
2051817466cbSJens Wiklander     if( R != NULL )
2052817466cbSJens Wiklander     {
2053817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
2054817466cbSJens Wiklander         X.s = A->s;
2055817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
2056817466cbSJens Wiklander 
2057817466cbSJens Wiklander         if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
2058817466cbSJens Wiklander             R->s = 1;
2059817466cbSJens Wiklander     }
2060817466cbSJens Wiklander 
2061817466cbSJens Wiklander cleanup:
2062817466cbSJens Wiklander 
2063817466cbSJens Wiklander     mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
206411fa71b9SJerome Forissier     mbedtls_mpi_free( &T1 );
206511fa71b9SJerome Forissier     mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
2066817466cbSJens Wiklander 
2067817466cbSJens Wiklander     return( ret );
2068817466cbSJens Wiklander }
2069817466cbSJens Wiklander 
2070817466cbSJens Wiklander /*
2071817466cbSJens Wiklander  * Division by int: A = Q * b + R
2072817466cbSJens Wiklander  */
20733d3b0591SJens Wiklander int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
20743d3b0591SJens Wiklander                          const mbedtls_mpi *A,
20753d3b0591SJens Wiklander                          mbedtls_mpi_sint b )
2076817466cbSJens Wiklander {
2077817466cbSJens Wiklander     mbedtls_mpi _B;
2078817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
20793d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
2080817466cbSJens Wiklander 
2081817466cbSJens Wiklander     p[0] = ( b < 0 ) ? -b : b;
2082817466cbSJens Wiklander     _B.s = ( b < 0 ) ? -1 : 1;
2083817466cbSJens Wiklander     _B.n = 1;
2084817466cbSJens Wiklander     _B.p = p;
2085817466cbSJens Wiklander 
2086817466cbSJens Wiklander     return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) );
2087817466cbSJens Wiklander }
2088817466cbSJens Wiklander 
2089817466cbSJens Wiklander /*
2090817466cbSJens Wiklander  * Modulo: R = A mod B
2091817466cbSJens Wiklander  */
2092817466cbSJens Wiklander int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
2093817466cbSJens Wiklander {
209411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
20953d3b0591SJens Wiklander     MPI_VALIDATE_RET( R != NULL );
20963d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
20973d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
2098817466cbSJens Wiklander 
2099817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
2100817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
2101817466cbSJens Wiklander 
2102817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
2103817466cbSJens Wiklander 
2104817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
2105817466cbSJens Wiklander       MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
2106817466cbSJens Wiklander 
2107817466cbSJens Wiklander     while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
2108817466cbSJens Wiklander       MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
2109817466cbSJens Wiklander 
2110817466cbSJens Wiklander cleanup:
2111817466cbSJens Wiklander 
2112817466cbSJens Wiklander     return( ret );
2113817466cbSJens Wiklander }
2114817466cbSJens Wiklander 
2115817466cbSJens Wiklander /*
2116817466cbSJens Wiklander  * Modulo: r = A mod b
2117817466cbSJens Wiklander  */
2118817466cbSJens Wiklander int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
2119817466cbSJens Wiklander {
2120817466cbSJens Wiklander     size_t i;
2121817466cbSJens Wiklander     mbedtls_mpi_uint x, y, z;
21223d3b0591SJens Wiklander     MPI_VALIDATE_RET( r != NULL );
21233d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
2124817466cbSJens Wiklander 
2125817466cbSJens Wiklander     if( b == 0 )
2126817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
2127817466cbSJens Wiklander 
2128817466cbSJens Wiklander     if( b < 0 )
2129817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
2130817466cbSJens Wiklander 
2131817466cbSJens Wiklander     /*
2132817466cbSJens Wiklander      * handle trivial cases
2133817466cbSJens Wiklander      */
2134817466cbSJens Wiklander     if( b == 1 )
2135817466cbSJens Wiklander     {
2136817466cbSJens Wiklander         *r = 0;
2137817466cbSJens Wiklander         return( 0 );
2138817466cbSJens Wiklander     }
2139817466cbSJens Wiklander 
2140817466cbSJens Wiklander     if( b == 2 )
2141817466cbSJens Wiklander     {
2142817466cbSJens Wiklander         *r = A->p[0] & 1;
2143817466cbSJens Wiklander         return( 0 );
2144817466cbSJens Wiklander     }
2145817466cbSJens Wiklander 
2146817466cbSJens Wiklander     /*
2147817466cbSJens Wiklander      * general case
2148817466cbSJens Wiklander      */
2149817466cbSJens Wiklander     for( i = A->n, y = 0; i > 0; i-- )
2150817466cbSJens Wiklander     {
2151817466cbSJens Wiklander         x  = A->p[i - 1];
2152817466cbSJens Wiklander         y  = ( y << biH ) | ( x >> biH );
2153817466cbSJens Wiklander         z  = y / b;
2154817466cbSJens Wiklander         y -= z * b;
2155817466cbSJens Wiklander 
2156817466cbSJens Wiklander         x <<= biH;
2157817466cbSJens Wiklander         y  = ( y << biH ) | ( x >> biH );
2158817466cbSJens Wiklander         z  = y / b;
2159817466cbSJens Wiklander         y -= z * b;
2160817466cbSJens Wiklander     }
2161817466cbSJens Wiklander 
2162817466cbSJens Wiklander     /*
2163817466cbSJens Wiklander      * If A is negative, then the current y represents a negative value.
2164817466cbSJens Wiklander      * Flipping it to the positive side.
2165817466cbSJens Wiklander      */
2166817466cbSJens Wiklander     if( A->s < 0 && y != 0 )
2167817466cbSJens Wiklander         y = b - y;
2168817466cbSJens Wiklander 
2169817466cbSJens Wiklander     *r = y;
2170817466cbSJens Wiklander 
2171817466cbSJens Wiklander     return( 0 );
2172817466cbSJens Wiklander }
2173817466cbSJens Wiklander 
2174817466cbSJens Wiklander /*
2175817466cbSJens Wiklander  * Fast Montgomery initialization (thanks to Tom St Denis)
2176817466cbSJens Wiklander  */
2177*7901324dSJerome Forissier static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
2178817466cbSJens Wiklander {
2179817466cbSJens Wiklander     mbedtls_mpi_uint x, m0 = N->p[0];
2180817466cbSJens Wiklander     unsigned int i;
2181817466cbSJens Wiklander 
2182817466cbSJens Wiklander     x  = m0;
2183817466cbSJens Wiklander     x += ( ( m0 + 2 ) & 4 ) << 1;
2184817466cbSJens Wiklander 
2185817466cbSJens Wiklander     for( i = biL; i >= 8; i /= 2 )
2186817466cbSJens Wiklander         x *= ( 2 - ( m0 * x ) );
2187817466cbSJens Wiklander 
2188817466cbSJens Wiklander     *mm = ~x + 1;
2189817466cbSJens Wiklander }
2190817466cbSJens Wiklander 
2191*7901324dSJerome Forissier void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
2192*7901324dSJerome Forissier {
2193*7901324dSJerome Forissier 	mpi_montg_init( mm, N );
2194*7901324dSJerome Forissier }
2195*7901324dSJerome Forissier 
2196*7901324dSJerome Forissier /** Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
2197*7901324dSJerome Forissier  *
2198*7901324dSJerome Forissier  * \param[in,out]   A   One of the numbers to multiply.
2199*7901324dSJerome Forissier  *                      It must have at least as many limbs as N
2200*7901324dSJerome Forissier  *                      (A->n >= N->n), and any limbs beyond n are ignored.
2201*7901324dSJerome Forissier  *                      On successful completion, A contains the result of
2202*7901324dSJerome Forissier  *                      the multiplication A * B * R^-1 mod N where
2203*7901324dSJerome Forissier  *                      R = (2^ciL)^n.
2204*7901324dSJerome Forissier  * \param[in]       B   One of the numbers to multiply.
2205*7901324dSJerome Forissier  *                      It must be nonzero and must not have more limbs than N
2206*7901324dSJerome Forissier  *                      (B->n <= N->n).
2207*7901324dSJerome Forissier  * \param[in]       N   The modulo. N must be odd.
2208*7901324dSJerome Forissier  * \param           mm  The value calculated by `mpi_montg_init(&mm, N)`.
2209*7901324dSJerome Forissier  *                      This is -N^-1 mod 2^ciL.
2210*7901324dSJerome Forissier  * \param[in,out]   T   A bignum for temporary storage.
2211*7901324dSJerome Forissier  *                      It must be at least twice the limb size of N plus 2
2212*7901324dSJerome Forissier  *                      (T->n >= 2 * (N->n + 1)).
2213*7901324dSJerome Forissier  *                      Its initial content is unused and
2214*7901324dSJerome Forissier  *                      its final content is indeterminate.
2215*7901324dSJerome Forissier  *                      Note that unlike the usual convention in the library
2216*7901324dSJerome Forissier  *                      for `const mbedtls_mpi*`, the content of T can change.
2217817466cbSJens Wiklander  */
2218*7901324dSJerome Forissier static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
2219817466cbSJens Wiklander                          const mbedtls_mpi *T )
2220817466cbSJens Wiklander {
2221817466cbSJens Wiklander     size_t i, n, m;
2222817466cbSJens Wiklander     mbedtls_mpi_uint u0, u1, *d;
2223817466cbSJens Wiklander 
2224817466cbSJens Wiklander     memset( T->p, 0, T->n * ciL );
2225817466cbSJens Wiklander 
2226817466cbSJens Wiklander     d = T->p;
2227817466cbSJens Wiklander     n = N->n;
2228817466cbSJens Wiklander     m = ( B->n < n ) ? B->n : n;
2229817466cbSJens Wiklander 
2230817466cbSJens Wiklander     for( i = 0; i < n; i++ )
2231817466cbSJens Wiklander     {
2232817466cbSJens Wiklander         /*
2233817466cbSJens Wiklander          * T = (T + u0*B + u1*N) / 2^biL
2234817466cbSJens Wiklander          */
2235817466cbSJens Wiklander         u0 = A->p[i];
2236817466cbSJens Wiklander         u1 = ( d[0] + u0 * B->p[0] ) * mm;
2237817466cbSJens Wiklander 
2238817466cbSJens Wiklander         mpi_mul_hlp( m, B->p, d, u0 );
2239817466cbSJens Wiklander         mpi_mul_hlp( n, N->p, d, u1 );
2240817466cbSJens Wiklander 
2241817466cbSJens Wiklander         *d++ = u0; d[n + 1] = 0;
2242817466cbSJens Wiklander     }
2243817466cbSJens Wiklander 
2244*7901324dSJerome Forissier     /* At this point, d is either the desired result or the desired result
2245*7901324dSJerome Forissier      * plus N. We now potentially subtract N, avoiding leaking whether the
2246*7901324dSJerome Forissier      * subtraction is performed through side channels. */
2247817466cbSJens Wiklander 
2248*7901324dSJerome Forissier     /* Copy the n least significant limbs of d to A, so that
2249*7901324dSJerome Forissier      * A = d if d < N (recall that N has n limbs). */
2250*7901324dSJerome Forissier     memcpy( A->p, d, n * ciL );
2251*7901324dSJerome Forissier     /* If d >= N then we want to set A to d - N. To prevent timing attacks,
2252*7901324dSJerome Forissier      * do the calculation without using conditional tests. */
2253*7901324dSJerome Forissier     /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
2254*7901324dSJerome Forissier     d[n] += 1;
2255*7901324dSJerome Forissier     d[n] -= mpi_sub_hlp( n, d, d, N->p );
2256*7901324dSJerome Forissier     /* If d0 < N then d < (2^biL)^n
2257*7901324dSJerome Forissier      * so d[n] == 0 and we want to keep A as it is.
2258*7901324dSJerome Forissier      * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
2259*7901324dSJerome Forissier      * so d[n] == 1 and we want to set A to the result of the subtraction
2260*7901324dSJerome Forissier      * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
2261*7901324dSJerome Forissier      * This exactly corresponds to a conditional assignment. */
2262*7901324dSJerome Forissier     mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );
2263*7901324dSJerome Forissier }
2264817466cbSJens Wiklander 
2265*7901324dSJerome Forissier void mbedtls_mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
2266*7901324dSJerome Forissier                           const mbedtls_mpi *T )
2267*7901324dSJerome Forissier {
2268*7901324dSJerome Forissier     mpi_montmul( A, B, N, mm, T);
2269817466cbSJens Wiklander }
2270817466cbSJens Wiklander 
2271817466cbSJens Wiklander /*
2272817466cbSJens Wiklander  * Montgomery reduction: A = A * R^-1 mod N
2273*7901324dSJerome Forissier  *
2274*7901324dSJerome Forissier  * See mpi_montmul() regarding constraints and guarantees on the parameters.
2275817466cbSJens Wiklander  */
2276*7901324dSJerome Forissier static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
227762f21181SJens Wiklander                          mbedtls_mpi_uint mm, const mbedtls_mpi *T )
2278817466cbSJens Wiklander {
2279817466cbSJens Wiklander     mbedtls_mpi_uint z = 1;
2280817466cbSJens Wiklander     mbedtls_mpi U;
2281817466cbSJens Wiklander 
2282817466cbSJens Wiklander     U.n = U.s = (int) z;
2283817466cbSJens Wiklander     U.p = &z;
2284817466cbSJens Wiklander 
2285*7901324dSJerome Forissier     mpi_montmul( A, &U, N, mm, T );
2286*7901324dSJerome Forissier }
2287*7901324dSJerome Forissier 
2288*7901324dSJerome Forissier void mbedtls_mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
2289*7901324dSJerome Forissier                           mbedtls_mpi_uint mm, const mbedtls_mpi *T )
2290*7901324dSJerome Forissier {
2291*7901324dSJerome Forissier     mpi_montred( A, N, mm, T );
2292*7901324dSJerome Forissier }
2293*7901324dSJerome Forissier 
2294*7901324dSJerome Forissier /*
2295*7901324dSJerome Forissier  * Constant-flow boolean "equal" comparison:
2296*7901324dSJerome Forissier  * return x == y
2297*7901324dSJerome Forissier  *
2298*7901324dSJerome Forissier  * This function can be used to write constant-time code by replacing branches
2299*7901324dSJerome Forissier  * with bit operations - it can be used in conjunction with
2300*7901324dSJerome Forissier  * mbedtls_ssl_cf_mask_from_bit().
2301*7901324dSJerome Forissier  *
2302*7901324dSJerome Forissier  * This function is implemented without using comparison operators, as those
2303*7901324dSJerome Forissier  * might be translated to branches by some compilers on some platforms.
2304*7901324dSJerome Forissier  */
2305*7901324dSJerome Forissier static size_t mbedtls_mpi_cf_bool_eq( size_t x, size_t y )
2306*7901324dSJerome Forissier {
2307*7901324dSJerome Forissier     /* diff = 0 if x == y, non-zero otherwise */
2308*7901324dSJerome Forissier     const size_t diff = x ^ y;
2309*7901324dSJerome Forissier 
2310*7901324dSJerome Forissier     /* MSVC has a warning about unary minus on unsigned integer types,
2311*7901324dSJerome Forissier      * but this is well-defined and precisely what we want to do here. */
2312*7901324dSJerome Forissier #if defined(_MSC_VER)
2313*7901324dSJerome Forissier #pragma warning( push )
2314*7901324dSJerome Forissier #pragma warning( disable : 4146 )
2315*7901324dSJerome Forissier #endif
2316*7901324dSJerome Forissier 
2317*7901324dSJerome Forissier     /* diff_msb's most significant bit is equal to x != y */
2318*7901324dSJerome Forissier     const size_t diff_msb = ( diff | (size_t) -diff );
2319*7901324dSJerome Forissier 
2320*7901324dSJerome Forissier #if defined(_MSC_VER)
2321*7901324dSJerome Forissier #pragma warning( pop )
2322*7901324dSJerome Forissier #endif
2323*7901324dSJerome Forissier 
2324*7901324dSJerome Forissier     /* diff1 = (x != y) ? 1 : 0 */
2325*7901324dSJerome Forissier     const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
2326*7901324dSJerome Forissier 
2327*7901324dSJerome Forissier     return( 1 ^ diff1 );
2328*7901324dSJerome Forissier }
2329*7901324dSJerome Forissier 
2330*7901324dSJerome Forissier /**
2331*7901324dSJerome Forissier  * Select an MPI from a table without leaking the index.
2332*7901324dSJerome Forissier  *
2333*7901324dSJerome Forissier  * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
2334*7901324dSJerome Forissier  * reads the entire table in order to avoid leaking the value of idx to an
2335*7901324dSJerome Forissier  * attacker able to observe memory access patterns.
2336*7901324dSJerome Forissier  *
2337*7901324dSJerome Forissier  * \param[out] R        Where to write the selected MPI.
2338*7901324dSJerome Forissier  * \param[in] T         The table to read from.
2339*7901324dSJerome Forissier  * \param[in] T_size    The number of elements in the table.
2340*7901324dSJerome Forissier  * \param[in] idx       The index of the element to select;
2341*7901324dSJerome Forissier  *                      this must satisfy 0 <= idx < T_size.
2342*7901324dSJerome Forissier  *
2343*7901324dSJerome Forissier  * \return \c 0 on success, or a negative error code.
2344*7901324dSJerome Forissier  */
2345*7901324dSJerome Forissier static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
2346*7901324dSJerome Forissier {
2347*7901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2348*7901324dSJerome Forissier 
2349*7901324dSJerome Forissier     for( size_t i = 0; i < T_size; i++ )
2350*7901324dSJerome Forissier     {
2351*7901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2352*7901324dSJerome Forissier                         (unsigned char) mbedtls_mpi_cf_bool_eq( i, idx ) ) );
2353*7901324dSJerome Forissier     }
2354*7901324dSJerome Forissier 
2355*7901324dSJerome Forissier cleanup:
2356*7901324dSJerome Forissier     return( ret );
2357817466cbSJens Wiklander }
2358817466cbSJens Wiklander 
2359817466cbSJens Wiklander /*
2360817466cbSJens Wiklander  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
2361817466cbSJens Wiklander  */
23623d3b0591SJens Wiklander int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
23633d3b0591SJens Wiklander                          const mbedtls_mpi *E, const mbedtls_mpi *N,
23643d3b0591SJens Wiklander                          mbedtls_mpi *_RR )
2365817466cbSJens Wiklander {
236611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2367817466cbSJens Wiklander     size_t wbits, wsize, one = 1;
2368817466cbSJens Wiklander     size_t i, j, nblimbs;
2369817466cbSJens Wiklander     size_t bufsize, nbits;
2370817466cbSJens Wiklander     mbedtls_mpi_uint ei, mm, state;
2371*7901324dSJerome Forissier     mbedtls_mpi RR, T, WW, Apos;
2372ad443200SJens Wiklander     mbedtls_mpi *W = NULL;
237341e5aa8fSJens Wiklander     const size_t array_size_W = 2 << MBEDTLS_MPI_WINDOW_SIZE;
2374817466cbSJens Wiklander     int neg;
2375817466cbSJens Wiklander 
23763d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
23773d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
23783d3b0591SJens Wiklander     MPI_VALIDATE_RET( E != NULL );
23793d3b0591SJens Wiklander     MPI_VALIDATE_RET( N != NULL );
23803d3b0591SJens Wiklander 
23813d3b0591SJens Wiklander     if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
2382817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2383817466cbSJens Wiklander 
2384817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2385817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2386817466cbSJens Wiklander 
2387*7901324dSJerome Forissier     if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
2388*7901324dSJerome Forissier         mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
2389*7901324dSJerome Forissier         return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2390*7901324dSJerome Forissier 
2391817466cbSJens Wiklander     /*
2392817466cbSJens Wiklander      * Init temps and window size
2393817466cbSJens Wiklander      */
2394*7901324dSJerome Forissier     mpi_montg_init( &mm, N );
2395*7901324dSJerome Forissier     mbedtls_mpi_init_mempool( &RR ); mbedtls_mpi_init( &T );
239698bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &Apos );
2397*7901324dSJerome Forissier     mbedtls_mpi_init_mempool( &WW );
2398817466cbSJens Wiklander 
2399817466cbSJens Wiklander     i = mbedtls_mpi_bitlen( E );
2400817466cbSJens Wiklander 
2401817466cbSJens Wiklander     wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2402817466cbSJens Wiklander             ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
2403817466cbSJens Wiklander 
24045b25c76aSJerome Forissier #if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
2405817466cbSJens Wiklander     if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2406817466cbSJens Wiklander         wsize = MBEDTLS_MPI_WINDOW_SIZE;
24075b25c76aSJerome Forissier #endif
2408817466cbSJens Wiklander 
2409817466cbSJens Wiklander     j = N->n + 1;
2410*7901324dSJerome Forissier     /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
2411*7901324dSJerome Forissier      * and mpi_montred() calls later. Here we ensure that W[1] and X are
2412*7901324dSJerome Forissier      * large enough, and later we'll grow other W[i] to the same length.
2413*7901324dSJerome Forissier      * They must not be shrunk midway through this function!
2414*7901324dSJerome Forissier      */
2415817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2416ad443200SJens Wiklander 
2417817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
2418817466cbSJens Wiklander 
2419817466cbSJens Wiklander     /*
2420817466cbSJens Wiklander      * Compensate for negative A (and correct at the end)
2421817466cbSJens Wiklander      */
2422817466cbSJens Wiklander     neg = ( A->s == -1 );
2423817466cbSJens Wiklander     if( neg )
2424817466cbSJens Wiklander     {
2425817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
2426817466cbSJens Wiklander         Apos.s = 1;
2427817466cbSJens Wiklander         A = &Apos;
2428817466cbSJens Wiklander     }
2429817466cbSJens Wiklander 
2430817466cbSJens Wiklander     /*
2431817466cbSJens Wiklander      * If 1st call, pre-compute R^2 mod N
2432817466cbSJens Wiklander      */
2433817466cbSJens Wiklander     if( _RR == NULL || _RR->p == NULL )
2434817466cbSJens Wiklander     {
2435817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2436817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2437817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
2438817466cbSJens Wiklander 
2439817466cbSJens Wiklander         if( _RR != NULL )
2440817466cbSJens Wiklander             memcpy( _RR, &RR, sizeof( mbedtls_mpi ) );
2441817466cbSJens Wiklander     }
2442817466cbSJens Wiklander     else
2443817466cbSJens Wiklander         memcpy( &RR, _RR, sizeof( mbedtls_mpi ) );
2444817466cbSJens Wiklander 
2445ad443200SJens Wiklander     W = mempool_alloc( mbedtls_mpi_mempool,
2446ad443200SJens Wiklander                        sizeof( mbedtls_mpi ) * array_size_W );
2447ad443200SJens Wiklander     if( W == NULL ) {
2448ad443200SJens Wiklander         ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
2449ad443200SJens Wiklander         goto cleanup;
2450ad443200SJens Wiklander     }
2451ad443200SJens Wiklander     for( i = 0; i < array_size_W; i++ )
2452ad443200SJens Wiklander         mbedtls_mpi_init_mempool( W + i );
2453ad443200SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1],  j ) );
2454ad443200SJens Wiklander 
2455817466cbSJens Wiklander     /*
2456817466cbSJens Wiklander      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2457817466cbSJens Wiklander      */
2458817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
2459*7901324dSJerome Forissier     {
2460817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
2461*7901324dSJerome Forissier         /* This should be a no-op because W[1] is already that large before
2462*7901324dSJerome Forissier          * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
2463*7901324dSJerome Forissier          * in mpi_montmul() below, so let's make sure. */
2464*7901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
2465*7901324dSJerome Forissier     }
2466817466cbSJens Wiklander     else
2467817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
2468817466cbSJens Wiklander 
2469*7901324dSJerome Forissier     /* Note that this is safe because W[1] always has at least N->n limbs
2470*7901324dSJerome Forissier      * (it grew above and was preserved by mbedtls_mpi_copy()). */
2471*7901324dSJerome Forissier     mpi_montmul( &W[1], &RR, N, mm, &T );
2472817466cbSJens Wiklander 
2473817466cbSJens Wiklander     /*
2474817466cbSJens Wiklander      * X = R^2 * R^-1 mod N = R mod N
2475817466cbSJens Wiklander      */
2476817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
2477*7901324dSJerome Forissier     mpi_montred( X, N, mm, &T );
2478817466cbSJens Wiklander 
2479817466cbSJens Wiklander     if( wsize > 1 )
2480817466cbSJens Wiklander     {
2481817466cbSJens Wiklander         /*
2482817466cbSJens Wiklander          * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2483817466cbSJens Wiklander          */
2484817466cbSJens Wiklander         j =  one << ( wsize - 1 );
2485817466cbSJens Wiklander 
2486817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2487817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1]    ) );
2488817466cbSJens Wiklander 
2489817466cbSJens Wiklander         for( i = 0; i < wsize - 1; i++ )
2490*7901324dSJerome Forissier             mpi_montmul( &W[j], &W[j], N, mm, &T );
2491817466cbSJens Wiklander 
2492817466cbSJens Wiklander         /*
2493817466cbSJens Wiklander          * W[i] = W[i - 1] * W[1]
2494817466cbSJens Wiklander          */
2495817466cbSJens Wiklander         for( i = j + 1; i < ( one << wsize ); i++ )
2496817466cbSJens Wiklander         {
2497817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2498817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
2499817466cbSJens Wiklander 
2500*7901324dSJerome Forissier             mpi_montmul( &W[i], &W[1], N, mm, &T );
2501817466cbSJens Wiklander         }
2502817466cbSJens Wiklander     }
2503817466cbSJens Wiklander 
2504817466cbSJens Wiklander     nblimbs = E->n;
2505817466cbSJens Wiklander     bufsize = 0;
2506817466cbSJens Wiklander     nbits   = 0;
2507817466cbSJens Wiklander     wbits   = 0;
2508817466cbSJens Wiklander     state   = 0;
2509817466cbSJens Wiklander 
2510817466cbSJens Wiklander     while( 1 )
2511817466cbSJens Wiklander     {
2512817466cbSJens Wiklander         if( bufsize == 0 )
2513817466cbSJens Wiklander         {
2514817466cbSJens Wiklander             if( nblimbs == 0 )
2515817466cbSJens Wiklander                 break;
2516817466cbSJens Wiklander 
2517817466cbSJens Wiklander             nblimbs--;
2518817466cbSJens Wiklander 
2519817466cbSJens Wiklander             bufsize = sizeof( mbedtls_mpi_uint ) << 3;
2520817466cbSJens Wiklander         }
2521817466cbSJens Wiklander 
2522817466cbSJens Wiklander         bufsize--;
2523817466cbSJens Wiklander 
2524817466cbSJens Wiklander         ei = (E->p[nblimbs] >> bufsize) & 1;
2525817466cbSJens Wiklander 
2526817466cbSJens Wiklander         /*
2527817466cbSJens Wiklander          * skip leading 0s
2528817466cbSJens Wiklander          */
2529817466cbSJens Wiklander         if( ei == 0 && state == 0 )
2530817466cbSJens Wiklander             continue;
2531817466cbSJens Wiklander 
2532817466cbSJens Wiklander         if( ei == 0 && state == 1 )
2533817466cbSJens Wiklander         {
2534817466cbSJens Wiklander             /*
2535817466cbSJens Wiklander              * out of window, square X
2536817466cbSJens Wiklander              */
2537*7901324dSJerome Forissier             mpi_montmul( X, X, N, mm, &T );
2538817466cbSJens Wiklander             continue;
2539817466cbSJens Wiklander         }
2540817466cbSJens Wiklander 
2541817466cbSJens Wiklander         /*
2542817466cbSJens Wiklander          * add ei to current window
2543817466cbSJens Wiklander          */
2544817466cbSJens Wiklander         state = 2;
2545817466cbSJens Wiklander 
2546817466cbSJens Wiklander         nbits++;
2547817466cbSJens Wiklander         wbits |= ( ei << ( wsize - nbits ) );
2548817466cbSJens Wiklander 
2549817466cbSJens Wiklander         if( nbits == wsize )
2550817466cbSJens Wiklander         {
2551817466cbSJens Wiklander             /*
2552817466cbSJens Wiklander              * X = X^wsize R^-1 mod N
2553817466cbSJens Wiklander              */
2554817466cbSJens Wiklander             for( i = 0; i < wsize; i++ )
2555*7901324dSJerome Forissier                 mpi_montmul( X, X, N, mm, &T );
2556817466cbSJens Wiklander 
2557817466cbSJens Wiklander             /*
2558817466cbSJens Wiklander              * X = X * W[wbits] R^-1 mod N
2559817466cbSJens Wiklander              */
2560*7901324dSJerome Forissier             MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
2561*7901324dSJerome Forissier             mpi_montmul( X, &WW, N, mm, &T );
2562817466cbSJens Wiklander 
2563817466cbSJens Wiklander             state--;
2564817466cbSJens Wiklander             nbits = 0;
2565817466cbSJens Wiklander             wbits = 0;
2566817466cbSJens Wiklander         }
2567817466cbSJens Wiklander     }
2568817466cbSJens Wiklander 
2569817466cbSJens Wiklander     /*
2570817466cbSJens Wiklander      * process the remaining bits
2571817466cbSJens Wiklander      */
2572817466cbSJens Wiklander     for( i = 0; i < nbits; i++ )
2573817466cbSJens Wiklander     {
2574*7901324dSJerome Forissier         mpi_montmul( X, X, N, mm, &T );
2575817466cbSJens Wiklander 
2576817466cbSJens Wiklander         wbits <<= 1;
2577817466cbSJens Wiklander 
2578817466cbSJens Wiklander         if( ( wbits & ( one << wsize ) ) != 0 )
2579*7901324dSJerome Forissier             mpi_montmul( X, &W[1], N, mm, &T );
2580817466cbSJens Wiklander     }
2581817466cbSJens Wiklander 
2582817466cbSJens Wiklander     /*
2583817466cbSJens Wiklander      * X = A^E * R * R^-1 mod N = A^E mod N
2584817466cbSJens Wiklander      */
2585*7901324dSJerome Forissier     mpi_montred( X, N, mm, &T );
2586817466cbSJens Wiklander 
2587817466cbSJens Wiklander     if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
2588817466cbSJens Wiklander     {
2589817466cbSJens Wiklander         X->s = -1;
2590817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
2591817466cbSJens Wiklander     }
2592817466cbSJens Wiklander 
2593817466cbSJens Wiklander cleanup:
2594817466cbSJens Wiklander 
2595ad443200SJens Wiklander     if( W )
259641e5aa8fSJens Wiklander         for( i = 0; i < array_size_W; i++ )
2597b99a4a18SJens Wiklander             mbedtls_mpi_free( W + i );
259841e5aa8fSJens Wiklander     mempool_free( mbedtls_mpi_mempool , W );
2599817466cbSJens Wiklander 
2600b99a4a18SJens Wiklander     mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
2601*7901324dSJerome Forissier     mbedtls_mpi_free( &WW );
2602817466cbSJens Wiklander 
2603817466cbSJens Wiklander     if( _RR == NULL || _RR->p == NULL )
2604817466cbSJens Wiklander         mbedtls_mpi_free( &RR );
2605817466cbSJens Wiklander 
2606817466cbSJens Wiklander     return( ret );
2607817466cbSJens Wiklander }
2608817466cbSJens Wiklander 
2609817466cbSJens Wiklander /*
2610817466cbSJens Wiklander  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
2611817466cbSJens Wiklander  */
2612817466cbSJens Wiklander int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
2613817466cbSJens Wiklander {
261411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2615817466cbSJens Wiklander     size_t lz, lzt;
261611fa71b9SJerome Forissier     mbedtls_mpi TA, TB;
2617817466cbSJens Wiklander 
26183d3b0591SJens Wiklander     MPI_VALIDATE_RET( G != NULL );
26193d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
26203d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
26213d3b0591SJens Wiklander 
262211fa71b9SJerome Forissier     mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB );
2623817466cbSJens Wiklander 
2624817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2625817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
2626817466cbSJens Wiklander 
2627817466cbSJens Wiklander     lz = mbedtls_mpi_lsb( &TA );
2628817466cbSJens Wiklander     lzt = mbedtls_mpi_lsb( &TB );
2629817466cbSJens Wiklander 
2630*7901324dSJerome Forissier     /* The loop below gives the correct result when A==0 but not when B==0.
2631*7901324dSJerome Forissier      * So have a special case for B==0. Leverage the fact that we just
2632*7901324dSJerome Forissier      * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
2633*7901324dSJerome Forissier      * slightly more efficient than cmp_int(). */
2634*7901324dSJerome Forissier     if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
2635*7901324dSJerome Forissier     {
2636*7901324dSJerome Forissier         ret = mbedtls_mpi_copy( G, A );
2637*7901324dSJerome Forissier         goto cleanup;
2638*7901324dSJerome Forissier     }
2639*7901324dSJerome Forissier 
2640817466cbSJens Wiklander     if( lzt < lz )
2641817466cbSJens Wiklander         lz = lzt;
2642817466cbSJens Wiklander 
2643817466cbSJens Wiklander     TA.s = TB.s = 1;
2644817466cbSJens Wiklander 
2645*7901324dSJerome Forissier     /* We mostly follow the procedure described in HAC 14.54, but with some
2646*7901324dSJerome Forissier      * minor differences:
2647*7901324dSJerome Forissier      * - Sequences of multiplications or divisions by 2 are grouped into a
2648*7901324dSJerome Forissier      *   single shift operation.
2649*7901324dSJerome Forissier      * - The procedure in HAC assumes that 0 < TB <= TA.
2650*7901324dSJerome Forissier      *     - The condition TB <= TA is not actually necessary for correctness.
2651*7901324dSJerome Forissier      *       TA and TB have symmetric roles except for the loop termination
2652*7901324dSJerome Forissier      *       condition, and the shifts at the beginning of the loop body
2653*7901324dSJerome Forissier      *       remove any significance from the ordering of TA vs TB before
2654*7901324dSJerome Forissier      *       the shifts.
2655*7901324dSJerome Forissier      *     - If TA = 0, the loop goes through 0 iterations and the result is
2656*7901324dSJerome Forissier      *       correctly TB.
2657*7901324dSJerome Forissier      *     - The case TB = 0 was short-circuited above.
2658*7901324dSJerome Forissier      *
2659*7901324dSJerome Forissier      * For the correctness proof below, decompose the original values of
2660*7901324dSJerome Forissier      * A and B as
2661*7901324dSJerome Forissier      *   A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
2662*7901324dSJerome Forissier      *   B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
2663*7901324dSJerome Forissier      * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
2664*7901324dSJerome Forissier      * and gcd(A',B') is odd or 0.
2665*7901324dSJerome Forissier      *
2666*7901324dSJerome Forissier      * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
2667*7901324dSJerome Forissier      * The code maintains the following invariant:
2668*7901324dSJerome Forissier      *     gcd(A,B) = 2^k * gcd(TA,TB) for some k   (I)
2669*7901324dSJerome Forissier      */
2670*7901324dSJerome Forissier 
2671*7901324dSJerome Forissier     /* Proof that the loop terminates:
2672*7901324dSJerome Forissier      * At each iteration, either the right-shift by 1 is made on a nonzero
2673*7901324dSJerome Forissier      * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
2674*7901324dSJerome Forissier      * by at least 1, or the right-shift by 1 is made on zero and then
2675*7901324dSJerome Forissier      * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
2676*7901324dSJerome Forissier      * since in that case TB is calculated from TB-TA with the condition TB>TA).
2677*7901324dSJerome Forissier      */
2678817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
2679817466cbSJens Wiklander     {
2680*7901324dSJerome Forissier         /* Divisions by 2 preserve the invariant (I). */
2681817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2682817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
2683817466cbSJens Wiklander 
2684*7901324dSJerome Forissier         /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
2685*7901324dSJerome Forissier          * TA-TB is even so the division by 2 has an integer result.
2686*7901324dSJerome Forissier          * Invariant (I) is preserved since any odd divisor of both TA and TB
2687*7901324dSJerome Forissier          * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2688*7901324dSJerome Forissier          * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
2689*7901324dSJerome Forissier          * divides TA.
2690*7901324dSJerome Forissier          */
2691817466cbSJens Wiklander         if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
2692817466cbSJens Wiklander         {
2693817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2694817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
2695817466cbSJens Wiklander         }
2696817466cbSJens Wiklander         else
2697817466cbSJens Wiklander         {
2698817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2699817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
2700817466cbSJens Wiklander         }
2701*7901324dSJerome Forissier         /* Note that one of TA or TB is still odd. */
2702817466cbSJens Wiklander     }
2703817466cbSJens Wiklander 
2704*7901324dSJerome Forissier     /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
2705*7901324dSJerome Forissier      * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
2706*7901324dSJerome Forissier      * - If there was at least one loop iteration, then one of TA or TB is odd,
2707*7901324dSJerome Forissier      *   and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
2708*7901324dSJerome Forissier      *   lz = min(a,b) so gcd(A,B) = 2^lz * TB.
2709*7901324dSJerome Forissier      * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
2710*7901324dSJerome Forissier      *   In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
2711*7901324dSJerome Forissier      */
2712*7901324dSJerome Forissier 
2713817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2714817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
2715817466cbSJens Wiklander 
2716817466cbSJens Wiklander cleanup:
2717817466cbSJens Wiklander 
271811fa71b9SJerome Forissier     mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
2719817466cbSJens Wiklander 
2720817466cbSJens Wiklander     return( ret );
2721817466cbSJens Wiklander }
2722817466cbSJens Wiklander 
2723*7901324dSJerome Forissier /* Fill X with n_bytes random bytes.
2724*7901324dSJerome Forissier  * X must already have room for those bytes.
2725*7901324dSJerome Forissier  * The ordering of the bytes returned from the RNG is suitable for
2726*7901324dSJerome Forissier  * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
2727*7901324dSJerome Forissier  * The size and sign of X are unchanged.
2728*7901324dSJerome Forissier  * n_bytes must not be 0.
2729*7901324dSJerome Forissier  */
2730*7901324dSJerome Forissier static int mpi_fill_random_internal(
2731*7901324dSJerome Forissier     mbedtls_mpi *X, size_t n_bytes,
2732*7901324dSJerome Forissier     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2733*7901324dSJerome Forissier {
2734*7901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2735*7901324dSJerome Forissier     const size_t limbs = CHARS_TO_LIMBS( n_bytes );
2736*7901324dSJerome Forissier     const size_t overhead = ( limbs * ciL ) - n_bytes;
2737*7901324dSJerome Forissier 
2738*7901324dSJerome Forissier     if( X->n < limbs )
2739*7901324dSJerome Forissier         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2740*7901324dSJerome Forissier 
2741*7901324dSJerome Forissier     memset( X->p, 0, overhead );
2742*7901324dSJerome Forissier     memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
2743*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
2744*7901324dSJerome Forissier     mpi_bigendian_to_host( X->p, limbs );
2745*7901324dSJerome Forissier 
2746*7901324dSJerome Forissier cleanup:
2747*7901324dSJerome Forissier     return( ret );
2748*7901324dSJerome Forissier }
2749*7901324dSJerome Forissier 
2750817466cbSJens Wiklander /*
2751817466cbSJens Wiklander  * Fill X with size bytes of random.
2752817466cbSJens Wiklander  *
2753817466cbSJens Wiklander  * Use a temporary bytes representation to make sure the result is the same
2754817466cbSJens Wiklander  * regardless of the platform endianness (useful when f_rng is actually
2755817466cbSJens Wiklander  * deterministic, eg for tests).
2756817466cbSJens Wiklander  */
2757817466cbSJens Wiklander int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
2758817466cbSJens Wiklander                      int (*f_rng)(void *, unsigned char *, size_t),
2759817466cbSJens Wiklander                      void *p_rng )
2760817466cbSJens Wiklander {
276111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
27625b25c76aSJerome Forissier     size_t const limbs = CHARS_TO_LIMBS( size );
27635b25c76aSJerome Forissier 
27643d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
27653d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
2766817466cbSJens Wiklander 
27675b25c76aSJerome Forissier     /* Ensure that target MPI has exactly the necessary number of limbs */
2768*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
2769*7901324dSJerome Forissier     if( size == 0 )
2770*7901324dSJerome Forissier         return( 0 );
2771817466cbSJens Wiklander 
2772*7901324dSJerome Forissier     ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
2773817466cbSJens Wiklander 
2774817466cbSJens Wiklander cleanup:
2775817466cbSJens Wiklander     return( ret );
2776817466cbSJens Wiklander }
2777817466cbSJens Wiklander 
2778*7901324dSJerome Forissier int mbedtls_mpi_random( mbedtls_mpi *X,
2779*7901324dSJerome Forissier                         mbedtls_mpi_sint min,
2780*7901324dSJerome Forissier                         const mbedtls_mpi *N,
2781*7901324dSJerome Forissier                         int (*f_rng)(void *, unsigned char *, size_t),
2782*7901324dSJerome Forissier                         void *p_rng )
2783*7901324dSJerome Forissier {
2784*7901324dSJerome Forissier     int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
2785*7901324dSJerome Forissier     int count;
2786*7901324dSJerome Forissier     unsigned lt_lower = 1, lt_upper = 0;
2787*7901324dSJerome Forissier     size_t n_bits = mbedtls_mpi_bitlen( N );
2788*7901324dSJerome Forissier     size_t n_bytes = ( n_bits + 7 ) / 8;
2789*7901324dSJerome Forissier     mbedtls_mpi lower_bound;
2790*7901324dSJerome Forissier 
2791*7901324dSJerome Forissier     if( min < 0 )
2792*7901324dSJerome Forissier         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2793*7901324dSJerome Forissier     if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
2794*7901324dSJerome Forissier         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2795*7901324dSJerome Forissier 
2796*7901324dSJerome Forissier     /*
2797*7901324dSJerome Forissier      * When min == 0, each try has at worst a probability 1/2 of failing
2798*7901324dSJerome Forissier      * (the msb has a probability 1/2 of being 0, and then the result will
2799*7901324dSJerome Forissier      * be < N), so after 30 tries failure probability is a most 2**(-30).
2800*7901324dSJerome Forissier      *
2801*7901324dSJerome Forissier      * When N is just below a power of 2, as is the case when generating
2802*7901324dSJerome Forissier      * a random scalar on most elliptic curves, 1 try is enough with
2803*7901324dSJerome Forissier      * overwhelming probability. When N is just above a power of 2,
2804*7901324dSJerome Forissier      * as when generating a random scalar on secp224k1, each try has
2805*7901324dSJerome Forissier      * a probability of failing that is almost 1/2.
2806*7901324dSJerome Forissier      *
2807*7901324dSJerome Forissier      * The probabilities are almost the same if min is nonzero but negligible
2808*7901324dSJerome Forissier      * compared to N. This is always the case when N is crypto-sized, but
2809*7901324dSJerome Forissier      * it's convenient to support small N for testing purposes. When N
2810*7901324dSJerome Forissier      * is small, use a higher repeat count, otherwise the probability of
2811*7901324dSJerome Forissier      * failure is macroscopic.
2812*7901324dSJerome Forissier      */
2813*7901324dSJerome Forissier     count = ( n_bytes > 4 ? 30 : 250 );
2814*7901324dSJerome Forissier 
2815*7901324dSJerome Forissier     mbedtls_mpi_init( &lower_bound );
2816*7901324dSJerome Forissier 
2817*7901324dSJerome Forissier     /* Ensure that target MPI has exactly the same number of limbs
2818*7901324dSJerome Forissier      * as the upper bound, even if the upper bound has leading zeros.
2819*7901324dSJerome Forissier      * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
2820*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
2821*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
2822*7901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
2823*7901324dSJerome Forissier 
2824*7901324dSJerome Forissier     /*
2825*7901324dSJerome Forissier      * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
2826*7901324dSJerome Forissier      * when f_rng is a suitably parametrized instance of HMAC_DRBG:
2827*7901324dSJerome Forissier      * - use the same byte ordering;
2828*7901324dSJerome Forissier      * - keep the leftmost n_bits bits of the generated octet string;
2829*7901324dSJerome Forissier      * - try until result is in the desired range.
2830*7901324dSJerome Forissier      * This also avoids any bias, which is especially important for ECDSA.
2831*7901324dSJerome Forissier      */
2832*7901324dSJerome Forissier     do
2833*7901324dSJerome Forissier     {
2834*7901324dSJerome Forissier         MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
2835*7901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
2836*7901324dSJerome Forissier 
2837*7901324dSJerome Forissier         if( --count == 0 )
2838*7901324dSJerome Forissier         {
2839*7901324dSJerome Forissier             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2840*7901324dSJerome Forissier             goto cleanup;
2841*7901324dSJerome Forissier         }
2842*7901324dSJerome Forissier 
2843*7901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
2844*7901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
2845*7901324dSJerome Forissier     }
2846*7901324dSJerome Forissier     while( lt_lower != 0 || lt_upper == 0 );
2847*7901324dSJerome Forissier 
2848*7901324dSJerome Forissier cleanup:
2849*7901324dSJerome Forissier     mbedtls_mpi_free( &lower_bound );
2850*7901324dSJerome Forissier     return( ret );
2851*7901324dSJerome Forissier }
2852*7901324dSJerome Forissier 
2853817466cbSJens Wiklander /*
2854817466cbSJens Wiklander  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
2855817466cbSJens Wiklander  */
2856817466cbSJens Wiklander int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
2857817466cbSJens Wiklander {
285811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2859817466cbSJens Wiklander     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
28603d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
28613d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
28623d3b0591SJens Wiklander     MPI_VALIDATE_RET( N != NULL );
2863817466cbSJens Wiklander 
2864817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
2865817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2866817466cbSJens Wiklander 
286798bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TU );
286898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &U1 ); mbedtls_mpi_init_mempool( &U2 );
286998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &G ); mbedtls_mpi_init_mempool( &TB );
287098bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &TV ); mbedtls_mpi_init_mempool( &V1 );
287198bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &V2 );
2872817466cbSJens Wiklander 
2873817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
2874817466cbSJens Wiklander 
2875817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
2876817466cbSJens Wiklander     {
2877817466cbSJens Wiklander         ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2878817466cbSJens Wiklander         goto cleanup;
2879817466cbSJens Wiklander     }
2880817466cbSJens Wiklander 
2881817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2882817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2883817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2884817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
2885817466cbSJens Wiklander 
2886817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2887817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2888817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2889817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
2890817466cbSJens Wiklander 
2891817466cbSJens Wiklander     do
2892817466cbSJens Wiklander     {
2893817466cbSJens Wiklander         while( ( TU.p[0] & 1 ) == 0 )
2894817466cbSJens Wiklander         {
2895817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
2896817466cbSJens Wiklander 
2897817466cbSJens Wiklander             if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2898817466cbSJens Wiklander             {
2899817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2900817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
2901817466cbSJens Wiklander             }
2902817466cbSJens Wiklander 
2903817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2904817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
2905817466cbSJens Wiklander         }
2906817466cbSJens Wiklander 
2907817466cbSJens Wiklander         while( ( TV.p[0] & 1 ) == 0 )
2908817466cbSJens Wiklander         {
2909817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
2910817466cbSJens Wiklander 
2911817466cbSJens Wiklander             if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2912817466cbSJens Wiklander             {
2913817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2914817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
2915817466cbSJens Wiklander             }
2916817466cbSJens Wiklander 
2917817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2918817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
2919817466cbSJens Wiklander         }
2920817466cbSJens Wiklander 
2921817466cbSJens Wiklander         if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
2922817466cbSJens Wiklander         {
2923817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2924817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2925817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
2926817466cbSJens Wiklander         }
2927817466cbSJens Wiklander         else
2928817466cbSJens Wiklander         {
2929817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2930817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2931817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
2932817466cbSJens Wiklander         }
2933817466cbSJens Wiklander     }
2934817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
2935817466cbSJens Wiklander 
2936817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2937817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
2938817466cbSJens Wiklander 
2939817466cbSJens Wiklander     while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2940817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
2941817466cbSJens Wiklander 
2942817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
2943817466cbSJens Wiklander 
2944817466cbSJens Wiklander cleanup:
2945817466cbSJens Wiklander 
2946817466cbSJens Wiklander     mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2947817466cbSJens Wiklander     mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2948817466cbSJens Wiklander     mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
2949817466cbSJens Wiklander 
2950817466cbSJens Wiklander     return( ret );
2951817466cbSJens Wiklander }
2952817466cbSJens Wiklander 
2953817466cbSJens Wiklander #if defined(MBEDTLS_GENPRIME)
2954817466cbSJens Wiklander 
2955817466cbSJens Wiklander static const int small_prime[] =
2956817466cbSJens Wiklander {
2957817466cbSJens Wiklander         3,    5,    7,   11,   13,   17,   19,   23,
2958817466cbSJens Wiklander        29,   31,   37,   41,   43,   47,   53,   59,
2959817466cbSJens Wiklander        61,   67,   71,   73,   79,   83,   89,   97,
2960817466cbSJens Wiklander       101,  103,  107,  109,  113,  127,  131,  137,
2961817466cbSJens Wiklander       139,  149,  151,  157,  163,  167,  173,  179,
2962817466cbSJens Wiklander       181,  191,  193,  197,  199,  211,  223,  227,
2963817466cbSJens Wiklander       229,  233,  239,  241,  251,  257,  263,  269,
2964817466cbSJens Wiklander       271,  277,  281,  283,  293,  307,  311,  313,
2965817466cbSJens Wiklander       317,  331,  337,  347,  349,  353,  359,  367,
2966817466cbSJens Wiklander       373,  379,  383,  389,  397,  401,  409,  419,
2967817466cbSJens Wiklander       421,  431,  433,  439,  443,  449,  457,  461,
2968817466cbSJens Wiklander       463,  467,  479,  487,  491,  499,  503,  509,
2969817466cbSJens Wiklander       521,  523,  541,  547,  557,  563,  569,  571,
2970817466cbSJens Wiklander       577,  587,  593,  599,  601,  607,  613,  617,
2971817466cbSJens Wiklander       619,  631,  641,  643,  647,  653,  659,  661,
2972817466cbSJens Wiklander       673,  677,  683,  691,  701,  709,  719,  727,
2973817466cbSJens Wiklander       733,  739,  743,  751,  757,  761,  769,  773,
2974817466cbSJens Wiklander       787,  797,  809,  811,  821,  823,  827,  829,
2975817466cbSJens Wiklander       839,  853,  857,  859,  863,  877,  881,  883,
2976817466cbSJens Wiklander       887,  907,  911,  919,  929,  937,  941,  947,
2977817466cbSJens Wiklander       953,  967,  971,  977,  983,  991,  997, -103
2978817466cbSJens Wiklander };
2979817466cbSJens Wiklander 
2980817466cbSJens Wiklander /*
2981817466cbSJens Wiklander  * Small divisors test (X must be positive)
2982817466cbSJens Wiklander  *
2983817466cbSJens Wiklander  * Return values:
2984817466cbSJens Wiklander  * 0: no small factor (possible prime, more tests needed)
2985817466cbSJens Wiklander  * 1: certain prime
2986817466cbSJens Wiklander  * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2987817466cbSJens Wiklander  * other negative: error
2988817466cbSJens Wiklander  */
2989817466cbSJens Wiklander static int mpi_check_small_factors( const mbedtls_mpi *X )
2990817466cbSJens Wiklander {
2991817466cbSJens Wiklander     int ret = 0;
2992817466cbSJens Wiklander     size_t i;
2993817466cbSJens Wiklander     mbedtls_mpi_uint r;
2994817466cbSJens Wiklander 
2995817466cbSJens Wiklander     if( ( X->p[0] & 1 ) == 0 )
2996817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2997817466cbSJens Wiklander 
2998817466cbSJens Wiklander     for( i = 0; small_prime[i] > 0; i++ )
2999817466cbSJens Wiklander     {
3000817466cbSJens Wiklander         if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
3001817466cbSJens Wiklander             return( 1 );
3002817466cbSJens Wiklander 
3003817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
3004817466cbSJens Wiklander 
3005817466cbSJens Wiklander         if( r == 0 )
3006817466cbSJens Wiklander             return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
3007817466cbSJens Wiklander     }
3008817466cbSJens Wiklander 
3009817466cbSJens Wiklander cleanup:
3010817466cbSJens Wiklander     return( ret );
3011817466cbSJens Wiklander }
3012817466cbSJens Wiklander 
3013817466cbSJens Wiklander /*
3014817466cbSJens Wiklander  * Miller-Rabin pseudo-primality test  (HAC 4.24)
3015817466cbSJens Wiklander  */
30163d3b0591SJens Wiklander static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
3017817466cbSJens Wiklander                              int (*f_rng)(void *, unsigned char *, size_t),
3018817466cbSJens Wiklander                              void *p_rng )
3019817466cbSJens Wiklander {
3020817466cbSJens Wiklander     int ret, count;
30213d3b0591SJens Wiklander     size_t i, j, k, s;
3022817466cbSJens Wiklander     mbedtls_mpi W, R, T, A, RR;
3023817466cbSJens Wiklander 
30243d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
30253d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
30263d3b0591SJens Wiklander 
302798bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &W ); mbedtls_mpi_init_mempool( &R );
302898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &T ); mbedtls_mpi_init_mempool( &A );
302998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &RR );
3030817466cbSJens Wiklander 
3031817466cbSJens Wiklander     /*
3032817466cbSJens Wiklander      * W = |X| - 1
3033817466cbSJens Wiklander      * R = W >> lsb( W )
3034817466cbSJens Wiklander      */
3035817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
3036817466cbSJens Wiklander     s = mbedtls_mpi_lsb( &W );
3037817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
3038817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
3039817466cbSJens Wiklander 
30403d3b0591SJens Wiklander     for( i = 0; i < rounds; i++ )
3041817466cbSJens Wiklander     {
3042817466cbSJens Wiklander         /*
3043817466cbSJens Wiklander          * pick a random A, 1 < A < |X| - 1
3044817466cbSJens Wiklander          */
3045817466cbSJens Wiklander         count = 0;
3046817466cbSJens Wiklander         do {
3047817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
3048817466cbSJens Wiklander 
3049817466cbSJens Wiklander             j = mbedtls_mpi_bitlen( &A );
3050817466cbSJens Wiklander             k = mbedtls_mpi_bitlen( &W );
3051817466cbSJens Wiklander             if (j > k) {
30523d3b0591SJens Wiklander                 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
3053817466cbSJens Wiklander             }
3054817466cbSJens Wiklander 
3055117cce93SJens Wiklander             if (count++ > 300) {
3056336e3299SJens Wiklander                 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
3057336e3299SJens Wiklander                 goto cleanup;
3058817466cbSJens Wiklander             }
3059817466cbSJens Wiklander 
3060817466cbSJens Wiklander         } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
3061817466cbSJens Wiklander                   mbedtls_mpi_cmp_int( &A, 1 )  <= 0    );
3062817466cbSJens Wiklander 
3063817466cbSJens Wiklander         /*
3064817466cbSJens Wiklander          * A = A^R mod |X|
3065817466cbSJens Wiklander          */
3066817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
3067817466cbSJens Wiklander 
3068817466cbSJens Wiklander         if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
3069817466cbSJens Wiklander             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
3070817466cbSJens Wiklander             continue;
3071817466cbSJens Wiklander 
3072817466cbSJens Wiklander         j = 1;
3073817466cbSJens Wiklander         while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
3074817466cbSJens Wiklander         {
3075817466cbSJens Wiklander             /*
3076817466cbSJens Wiklander              * A = A * A mod |X|
3077817466cbSJens Wiklander              */
3078817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
3079817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X  ) );
3080817466cbSJens Wiklander 
3081817466cbSJens Wiklander             if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
3082817466cbSJens Wiklander                 break;
3083817466cbSJens Wiklander 
3084817466cbSJens Wiklander             j++;
3085817466cbSJens Wiklander         }
3086817466cbSJens Wiklander 
3087817466cbSJens Wiklander         /*
3088817466cbSJens Wiklander          * not prime if A != |X| - 1 or A == 1
3089817466cbSJens Wiklander          */
3090817466cbSJens Wiklander         if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
3091817466cbSJens Wiklander             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
3092817466cbSJens Wiklander         {
3093817466cbSJens Wiklander             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
3094817466cbSJens Wiklander             break;
3095817466cbSJens Wiklander         }
3096817466cbSJens Wiklander     }
3097817466cbSJens Wiklander 
3098817466cbSJens Wiklander cleanup:
30993d3b0591SJens Wiklander     mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
31003d3b0591SJens Wiklander     mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
3101817466cbSJens Wiklander     mbedtls_mpi_free( &RR );
3102817466cbSJens Wiklander 
3103817466cbSJens Wiklander     return( ret );
3104817466cbSJens Wiklander }
3105817466cbSJens Wiklander 
3106817466cbSJens Wiklander /*
3107817466cbSJens Wiklander  * Pseudo-primality test: small factors, then Miller-Rabin
3108817466cbSJens Wiklander  */
31093d3b0591SJens Wiklander int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
3110817466cbSJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t),
3111817466cbSJens Wiklander                               void *p_rng )
3112817466cbSJens Wiklander {
311311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3114817466cbSJens Wiklander     mbedtls_mpi XX;
31153d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
31163d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
3117817466cbSJens Wiklander 
3118817466cbSJens Wiklander     XX.s = 1;
3119817466cbSJens Wiklander     XX.n = X->n;
3120817466cbSJens Wiklander     XX.p = X->p;
3121817466cbSJens Wiklander 
3122817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
3123817466cbSJens Wiklander         mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
3124817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
3125817466cbSJens Wiklander 
3126817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
3127817466cbSJens Wiklander         return( 0 );
3128817466cbSJens Wiklander 
3129817466cbSJens Wiklander     if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
3130817466cbSJens Wiklander     {
3131817466cbSJens Wiklander         if( ret == 1 )
3132817466cbSJens Wiklander             return( 0 );
3133817466cbSJens Wiklander 
3134817466cbSJens Wiklander         return( ret );
3135817466cbSJens Wiklander     }
3136817466cbSJens Wiklander 
31373d3b0591SJens Wiklander     return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
3138817466cbSJens Wiklander }
3139817466cbSJens Wiklander 
31403d3b0591SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED)
3141817466cbSJens Wiklander /*
31423d3b0591SJens Wiklander  * Pseudo-primality test, error probability 2^-80
3143817466cbSJens Wiklander  */
31443d3b0591SJens Wiklander int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
3145817466cbSJens Wiklander                   int (*f_rng)(void *, unsigned char *, size_t),
3146817466cbSJens Wiklander                   void *p_rng )
3147817466cbSJens Wiklander {
31483d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
31493d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
31503d3b0591SJens Wiklander 
31513d3b0591SJens Wiklander     /*
31523d3b0591SJens Wiklander      * In the past our key generation aimed for an error rate of at most
31533d3b0591SJens Wiklander      * 2^-80. Since this function is deprecated, aim for the same certainty
31543d3b0591SJens Wiklander      * here as well.
31553d3b0591SJens Wiklander      */
31563d3b0591SJens Wiklander     return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
31573d3b0591SJens Wiklander }
31583d3b0591SJens Wiklander #endif
31593d3b0591SJens Wiklander 
31603d3b0591SJens Wiklander /*
31613d3b0591SJens Wiklander  * Prime number generation
31623d3b0591SJens Wiklander  *
31633d3b0591SJens Wiklander  * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
31643d3b0591SJens Wiklander  * be either 1024 bits or 1536 bits long, and flags must contain
31653d3b0591SJens Wiklander  * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
31663d3b0591SJens Wiklander  */
31673d3b0591SJens Wiklander int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
31683d3b0591SJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t),
31693d3b0591SJens Wiklander                    void *p_rng )
31703d3b0591SJens Wiklander {
31713d3b0591SJens Wiklander #ifdef MBEDTLS_HAVE_INT64
31723d3b0591SJens Wiklander // ceil(2^63.5)
31733d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
31743d3b0591SJens Wiklander #else
31753d3b0591SJens Wiklander // ceil(2^31.5)
31763d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
31773d3b0591SJens Wiklander #endif
31783d3b0591SJens Wiklander     int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
3179817466cbSJens Wiklander     size_t k, n;
31803d3b0591SJens Wiklander     int rounds;
3181817466cbSJens Wiklander     mbedtls_mpi_uint r;
3182817466cbSJens Wiklander     mbedtls_mpi Y;
3183817466cbSJens Wiklander 
31843d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
31853d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
31863d3b0591SJens Wiklander 
3187817466cbSJens Wiklander     if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
3188817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
3189817466cbSJens Wiklander 
319098bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &Y );
3191817466cbSJens Wiklander 
3192817466cbSJens Wiklander     n = BITS_TO_LIMBS( nbits );
3193817466cbSJens Wiklander 
31943d3b0591SJens Wiklander     if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
31953d3b0591SJens Wiklander     {
31963d3b0591SJens Wiklander         /*
31973d3b0591SJens Wiklander          * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
31983d3b0591SJens Wiklander          */
31993d3b0591SJens Wiklander         rounds = ( ( nbits >= 1300 ) ?  2 : ( nbits >=  850 ) ?  3 :
32003d3b0591SJens Wiklander                    ( nbits >=  650 ) ?  4 : ( nbits >=  350 ) ?  8 :
32013d3b0591SJens Wiklander                    ( nbits >=  250 ) ? 12 : ( nbits >=  150 ) ? 18 : 27 );
32023d3b0591SJens Wiklander     }
32033d3b0591SJens Wiklander     else
32043d3b0591SJens Wiklander     {
32053d3b0591SJens Wiklander         /*
32063d3b0591SJens Wiklander          * 2^-100 error probability, number of rounds computed based on HAC,
32073d3b0591SJens Wiklander          * fact 4.48
32083d3b0591SJens Wiklander          */
32093d3b0591SJens Wiklander         rounds = ( ( nbits >= 1450 ) ?  4 : ( nbits >=  1150 ) ?  5 :
32103d3b0591SJens Wiklander                    ( nbits >= 1000 ) ?  6 : ( nbits >=   850 ) ?  7 :
32113d3b0591SJens Wiklander                    ( nbits >=  750 ) ?  8 : ( nbits >=   500 ) ? 13 :
32123d3b0591SJens Wiklander                    ( nbits >=  250 ) ? 28 : ( nbits >=   150 ) ? 40 : 51 );
32133d3b0591SJens Wiklander     }
32143d3b0591SJens Wiklander 
32153d3b0591SJens Wiklander     while( 1 )
32163d3b0591SJens Wiklander     {
3217817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
32183d3b0591SJens Wiklander         /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
32193d3b0591SJens Wiklander         if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
3220817466cbSJens Wiklander 
32213d3b0591SJens Wiklander         k = n * biL;
32223d3b0591SJens Wiklander         if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
3223817466cbSJens Wiklander         X->p[0] |= 1;
3224817466cbSJens Wiklander 
32253d3b0591SJens Wiklander         if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
3226817466cbSJens Wiklander         {
32273d3b0591SJens Wiklander             ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
32283d3b0591SJens Wiklander 
3229817466cbSJens Wiklander             if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
3230817466cbSJens Wiklander                 goto cleanup;
3231817466cbSJens Wiklander         }
3232817466cbSJens Wiklander         else
3233817466cbSJens Wiklander         {
3234817466cbSJens Wiklander             /*
3235817466cbSJens Wiklander              * An necessary condition for Y and X = 2Y + 1 to be prime
3236817466cbSJens Wiklander              * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
3237817466cbSJens Wiklander              * Make sure it is satisfied, while keeping X = 3 mod 4
3238817466cbSJens Wiklander              */
3239817466cbSJens Wiklander 
3240817466cbSJens Wiklander             X->p[0] |= 2;
3241817466cbSJens Wiklander 
3242817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
3243817466cbSJens Wiklander             if( r == 0 )
3244817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
3245817466cbSJens Wiklander             else if( r == 1 )
3246817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
3247817466cbSJens Wiklander 
3248817466cbSJens Wiklander             /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
3249817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
3250817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
3251817466cbSJens Wiklander 
3252817466cbSJens Wiklander             while( 1 )
3253817466cbSJens Wiklander             {
3254817466cbSJens Wiklander                 /*
3255817466cbSJens Wiklander                  * First, check small factors for X and Y
3256817466cbSJens Wiklander                  * before doing Miller-Rabin on any of them
3257817466cbSJens Wiklander                  */
3258817466cbSJens Wiklander                 if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
3259817466cbSJens Wiklander                     ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
32603d3b0591SJens Wiklander                     ( ret = mpi_miller_rabin(  X, rounds, f_rng, p_rng  ) )
32613d3b0591SJens Wiklander                                                                     == 0 &&
32623d3b0591SJens Wiklander                     ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng  ) )
32633d3b0591SJens Wiklander                                                                     == 0 )
32643d3b0591SJens Wiklander                     goto cleanup;
3265817466cbSJens Wiklander 
3266817466cbSJens Wiklander                 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
3267817466cbSJens Wiklander                     goto cleanup;
3268817466cbSJens Wiklander 
3269817466cbSJens Wiklander                 /*
3270817466cbSJens Wiklander                  * Next candidates. We want to preserve Y = (X-1) / 2 and
3271817466cbSJens Wiklander                  * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
3272817466cbSJens Wiklander                  * so up Y by 6 and X by 12.
3273817466cbSJens Wiklander                  */
3274817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(  X,  X, 12 ) );
3275817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6  ) );
3276817466cbSJens Wiklander             }
3277817466cbSJens Wiklander         }
32783d3b0591SJens Wiklander     }
3279817466cbSJens Wiklander 
3280817466cbSJens Wiklander cleanup:
3281817466cbSJens Wiklander 
3282817466cbSJens Wiklander     mbedtls_mpi_free( &Y );
3283817466cbSJens Wiklander 
3284817466cbSJens Wiklander     return( ret );
3285817466cbSJens Wiklander }
3286817466cbSJens Wiklander 
3287817466cbSJens Wiklander #endif /* MBEDTLS_GENPRIME */
3288817466cbSJens Wiklander 
3289817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
3290817466cbSJens Wiklander 
3291817466cbSJens Wiklander #define GCD_PAIR_COUNT  3
3292817466cbSJens Wiklander 
3293817466cbSJens Wiklander static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3294817466cbSJens Wiklander {
3295817466cbSJens Wiklander     { 693, 609, 21 },
3296817466cbSJens Wiklander     { 1764, 868, 28 },
3297817466cbSJens Wiklander     { 768454923, 542167814, 1 }
3298817466cbSJens Wiklander };
3299817466cbSJens Wiklander 
3300817466cbSJens Wiklander /*
3301817466cbSJens Wiklander  * Checkup routine
3302817466cbSJens Wiklander  */
3303817466cbSJens Wiklander int mbedtls_mpi_self_test( int verbose )
3304817466cbSJens Wiklander {
3305817466cbSJens Wiklander     int ret, i;
3306817466cbSJens Wiklander     mbedtls_mpi A, E, N, X, Y, U, V;
3307817466cbSJens Wiklander 
330898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &A ); mbedtls_mpi_init_mempool( &E );
330998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &N ); mbedtls_mpi_init_mempool( &X );
331098bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &Y ); mbedtls_mpi_init_mempool( &U );
331198bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &V );
3312817466cbSJens Wiklander 
3313817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
3314817466cbSJens Wiklander         "EFE021C2645FD1DC586E69184AF4A31E" \
3315817466cbSJens Wiklander         "D5F53E93B5F123FA41680867BA110131" \
3316817466cbSJens Wiklander         "944FE7952E2517337780CB0DB80E61AA" \
3317817466cbSJens Wiklander         "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3318817466cbSJens Wiklander 
3319817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
3320817466cbSJens Wiklander         "B2E7EFD37075B9F03FF989C7C5051C20" \
3321817466cbSJens Wiklander         "34D2A323810251127E7BF8625A4F49A5" \
3322817466cbSJens Wiklander         "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3323817466cbSJens Wiklander         "5B5C25763222FEFCCFC38B832366C29E" ) );
3324817466cbSJens Wiklander 
3325817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
3326817466cbSJens Wiklander         "0066A198186C18C10B2F5ED9B522752A" \
3327817466cbSJens Wiklander         "9830B69916E535C8F047518A889A43A5" \
3328817466cbSJens Wiklander         "94B6BED27A168D31D4A52F88925AA8F5" ) );
3329817466cbSJens Wiklander 
3330817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
3331817466cbSJens Wiklander 
3332817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3333817466cbSJens Wiklander         "602AB7ECA597A3D6B56FF9829A5E8B85" \
3334817466cbSJens Wiklander         "9E857EA95A03512E2BAE7391688D264A" \
3335817466cbSJens Wiklander         "A5663B0341DB9CCFD2C4C5F421FEC814" \
3336817466cbSJens Wiklander         "8001B72E848A38CAE1C65F78E56ABDEF" \
3337817466cbSJens Wiklander         "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3338817466cbSJens Wiklander         "ECF677152EF804370C1A305CAF3B5BF1" \
3339817466cbSJens Wiklander         "30879B56C61DE584A0F53A2447A51E" ) );
3340817466cbSJens Wiklander 
3341817466cbSJens Wiklander     if( verbose != 0 )
3342817466cbSJens Wiklander         mbedtls_printf( "  MPI test #1 (mul_mpi): " );
3343817466cbSJens Wiklander 
3344817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3345817466cbSJens Wiklander     {
3346817466cbSJens Wiklander         if( verbose != 0 )
3347817466cbSJens Wiklander             mbedtls_printf( "failed\n" );
3348817466cbSJens Wiklander 
3349817466cbSJens Wiklander         ret = 1;
3350817466cbSJens Wiklander         goto cleanup;
3351817466cbSJens Wiklander     }
3352817466cbSJens Wiklander 
3353817466cbSJens Wiklander     if( verbose != 0 )
3354817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3355817466cbSJens Wiklander 
3356817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
3357817466cbSJens Wiklander 
3358817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3359817466cbSJens Wiklander         "256567336059E52CAE22925474705F39A94" ) );
3360817466cbSJens Wiklander 
3361817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
3362817466cbSJens Wiklander         "6613F26162223DF488E9CD48CC132C7A" \
3363817466cbSJens Wiklander         "0AC93C701B001B092E4E5B9F73BCD27B" \
3364817466cbSJens Wiklander         "9EE50D0657C77F374E903CDFA4C642" ) );
3365817466cbSJens Wiklander 
3366817466cbSJens Wiklander     if( verbose != 0 )
3367817466cbSJens Wiklander         mbedtls_printf( "  MPI test #2 (div_mpi): " );
3368817466cbSJens Wiklander 
3369817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3370817466cbSJens Wiklander         mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
3371817466cbSJens Wiklander     {
3372817466cbSJens Wiklander         if( verbose != 0 )
3373817466cbSJens Wiklander             mbedtls_printf( "failed\n" );
3374817466cbSJens Wiklander 
3375817466cbSJens Wiklander         ret = 1;
3376817466cbSJens Wiklander         goto cleanup;
3377817466cbSJens Wiklander     }
3378817466cbSJens Wiklander 
3379817466cbSJens Wiklander     if( verbose != 0 )
3380817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3381817466cbSJens Wiklander 
3382817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
3383817466cbSJens Wiklander 
3384817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3385817466cbSJens Wiklander         "36E139AEA55215609D2816998ED020BB" \
3386817466cbSJens Wiklander         "BD96C37890F65171D948E9BC7CBAA4D9" \
3387817466cbSJens Wiklander         "325D24D6A3C12710F10A09FA08AB87" ) );
3388817466cbSJens Wiklander 
3389817466cbSJens Wiklander     if( verbose != 0 )
3390817466cbSJens Wiklander         mbedtls_printf( "  MPI test #3 (exp_mod): " );
3391817466cbSJens Wiklander 
3392817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3393817466cbSJens Wiklander     {
3394817466cbSJens Wiklander         if( verbose != 0 )
3395817466cbSJens Wiklander             mbedtls_printf( "failed\n" );
3396817466cbSJens Wiklander 
3397817466cbSJens Wiklander         ret = 1;
3398817466cbSJens Wiklander         goto cleanup;
3399817466cbSJens Wiklander     }
3400817466cbSJens Wiklander 
3401817466cbSJens Wiklander     if( verbose != 0 )
3402817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3403817466cbSJens Wiklander 
3404817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
3405817466cbSJens Wiklander 
3406817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3407817466cbSJens Wiklander         "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3408817466cbSJens Wiklander         "C3DBA76456363A10869622EAC2DD84EC" \
3409817466cbSJens Wiklander         "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3410817466cbSJens Wiklander 
3411817466cbSJens Wiklander     if( verbose != 0 )
3412817466cbSJens Wiklander         mbedtls_printf( "  MPI test #4 (inv_mod): " );
3413817466cbSJens Wiklander 
3414817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3415817466cbSJens Wiklander     {
3416817466cbSJens Wiklander         if( verbose != 0 )
3417817466cbSJens Wiklander             mbedtls_printf( "failed\n" );
3418817466cbSJens Wiklander 
3419817466cbSJens Wiklander         ret = 1;
3420817466cbSJens Wiklander         goto cleanup;
3421817466cbSJens Wiklander     }
3422817466cbSJens Wiklander 
3423817466cbSJens Wiklander     if( verbose != 0 )
3424817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3425817466cbSJens Wiklander 
3426817466cbSJens Wiklander     if( verbose != 0 )
3427817466cbSJens Wiklander         mbedtls_printf( "  MPI test #5 (simple gcd): " );
3428817466cbSJens Wiklander 
3429817466cbSJens Wiklander     for( i = 0; i < GCD_PAIR_COUNT; i++ )
3430817466cbSJens Wiklander     {
3431817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3432817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
3433817466cbSJens Wiklander 
3434817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
3435817466cbSJens Wiklander 
3436817466cbSJens Wiklander         if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
3437817466cbSJens Wiklander         {
3438817466cbSJens Wiklander             if( verbose != 0 )
3439817466cbSJens Wiklander                 mbedtls_printf( "failed at %d\n", i );
3440817466cbSJens Wiklander 
3441817466cbSJens Wiklander             ret = 1;
3442817466cbSJens Wiklander             goto cleanup;
3443817466cbSJens Wiklander         }
3444817466cbSJens Wiklander     }
3445817466cbSJens Wiklander 
3446817466cbSJens Wiklander     if( verbose != 0 )
3447817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3448817466cbSJens Wiklander 
3449817466cbSJens Wiklander cleanup:
3450817466cbSJens Wiklander 
3451817466cbSJens Wiklander     if( ret != 0 && verbose != 0 )
3452*7901324dSJerome Forissier         mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
3453817466cbSJens Wiklander 
3454817466cbSJens Wiklander     mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3455817466cbSJens Wiklander     mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
3456817466cbSJens Wiklander 
3457817466cbSJens Wiklander     if( verbose != 0 )
3458817466cbSJens Wiklander         mbedtls_printf( "\n" );
3459817466cbSJens Wiklander 
3460817466cbSJens Wiklander     return( ret );
3461817466cbSJens Wiklander }
3462817466cbSJens Wiklander 
3463817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
3464817466cbSJens Wiklander 
3465817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */
3466