xref: /optee_os/lib/libmbedtls/mbedtls/library/bignum.c (revision 039e02df2716a0ed886b56e1e07b7ac1d8597228)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Multi-precision integer library
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome 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 
367901324dSJerome 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"
44*039e02dfSJerome Forissier #include "constant_time_internal.h"
45817466cbSJens Wiklander 
46*039e02dfSJerome Forissier #include <limits.h>
47817466cbSJens Wiklander #include <string.h>
48817466cbSJens Wiklander 
49817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
50817466cbSJens Wiklander #include "mbedtls/platform.h"
51817466cbSJens Wiklander #else
52817466cbSJens Wiklander #include <stdio.h>
53817466cbSJens Wiklander #include <stdlib.h>
54817466cbSJens Wiklander #define mbedtls_printf     printf
55817466cbSJens Wiklander #define mbedtls_calloc    calloc
56817466cbSJens Wiklander #define mbedtls_free       free
57817466cbSJens Wiklander #endif
58817466cbSJens Wiklander 
5998bd5fe3SJens Wiklander #include <mempool.h>
60b99a4a18SJens Wiklander #include <util.h>
6198bd5fe3SJens Wiklander 
623d3b0591SJens Wiklander #define MPI_VALIDATE_RET( cond )                                       \
633d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA )
643d3b0591SJens Wiklander #define MPI_VALIDATE( cond )                                           \
653d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE( cond )
66817466cbSJens Wiklander 
67817466cbSJens Wiklander #define ciL    (sizeof(mbedtls_mpi_uint))         /* chars in limb  */
68817466cbSJens Wiklander #define biL    (ciL << 3)               /* bits  in limb  */
69817466cbSJens Wiklander #define biH    (ciL << 2)               /* half limb size */
70817466cbSJens Wiklander 
71817466cbSJens Wiklander #define MPI_SIZE_T_MAX  ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
72817466cbSJens Wiklander 
73817466cbSJens Wiklander /*
74817466cbSJens Wiklander  * Convert between bits/chars and number of limbs
75817466cbSJens Wiklander  * Divide first in order to avoid potential overflows
76817466cbSJens Wiklander  */
77817466cbSJens Wiklander #define BITS_TO_LIMBS(i)  ( (i) / biL + ( (i) % biL != 0 ) )
78817466cbSJens Wiklander #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) )
79817466cbSJens Wiklander 
8098bd5fe3SJens Wiklander void *mbedtls_mpi_mempool;
8198bd5fe3SJens Wiklander 
823d3b0591SJens Wiklander /* Implementation that should never be optimized out by the compiler */
833d3b0591SJens Wiklander static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n )
843d3b0591SJens Wiklander {
853d3b0591SJens Wiklander     mbedtls_platform_zeroize( v, ciL * n );
863d3b0591SJens Wiklander }
873d3b0591SJens Wiklander 
88817466cbSJens Wiklander /*
89817466cbSJens Wiklander  * Initialize one MPI
90817466cbSJens Wiklander  */
913d3b0591SJens Wiklander static void mpi_init( mbedtls_mpi *X, short use_mempool )
92817466cbSJens Wiklander {
933d3b0591SJens Wiklander     MPI_VALIDATE( X != NULL );
94817466cbSJens Wiklander 
953d3b0591SJens Wiklander     X->s = 1;
963d3b0591SJens Wiklander     X->use_mempool = use_mempool;
973d3b0591SJens Wiklander     X->n = 0;
983d3b0591SJens Wiklander     X->p = NULL;
99817466cbSJens Wiklander }
100817466cbSJens Wiklander 
10198bd5fe3SJens Wiklander void mbedtls_mpi_init( mbedtls_mpi *X )
10298bd5fe3SJens Wiklander {
1033d3b0591SJens Wiklander     mpi_init( X, 0 /*use_mempool*/ );
10498bd5fe3SJens Wiklander }
10598bd5fe3SJens Wiklander 
10698bd5fe3SJens Wiklander void mbedtls_mpi_init_mempool( mbedtls_mpi *X )
10798bd5fe3SJens Wiklander {
1083d3b0591SJens Wiklander     mpi_init( X, !!mbedtls_mpi_mempool /*use_mempool*/ );
10998bd5fe3SJens Wiklander }
11098bd5fe3SJens Wiklander 
111817466cbSJens Wiklander /*
112817466cbSJens Wiklander  * Unallocate one MPI
113817466cbSJens Wiklander  */
114817466cbSJens Wiklander void mbedtls_mpi_free( mbedtls_mpi *X )
115817466cbSJens Wiklander {
116817466cbSJens Wiklander     if( X == NULL )
117817466cbSJens Wiklander         return;
118817466cbSJens Wiklander 
119817466cbSJens Wiklander     if( X->p != NULL )
120817466cbSJens Wiklander     {
121817466cbSJens Wiklander         mbedtls_mpi_zeroize( X->p, X->n );
1223d3b0591SJens Wiklander         if( X->use_mempool )
12318c5148dSJens Wiklander             mempool_free( mbedtls_mpi_mempool, X->p );
1243d3b0591SJens Wiklander         else
1253d3b0591SJens Wiklander             mbedtls_free( X->p );
126817466cbSJens Wiklander     }
127817466cbSJens Wiklander 
128817466cbSJens Wiklander     X->s = 1;
129817466cbSJens Wiklander     X->n = 0;
1303d3b0591SJens Wiklander     X->p = NULL;
131817466cbSJens Wiklander }
132817466cbSJens Wiklander 
133817466cbSJens Wiklander /*
134817466cbSJens Wiklander  * Enlarge to the specified number of limbs
135817466cbSJens Wiklander  */
136817466cbSJens Wiklander int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs )
137817466cbSJens Wiklander {
138817466cbSJens Wiklander     mbedtls_mpi_uint *p;
1393d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
140817466cbSJens Wiklander 
141817466cbSJens Wiklander     if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
142817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
143817466cbSJens Wiklander 
1443d3b0591SJens Wiklander     if( X->n < nblimbs )
1453d3b0591SJens Wiklander     {
1463d3b0591SJens Wiklander         if( X->use_mempool )
1473d3b0591SJens Wiklander         {
1483d3b0591SJens Wiklander             p = mempool_alloc( mbedtls_mpi_mempool, nblimbs * ciL );
14918c5148dSJens Wiklander             if( p == NULL )
15018c5148dSJens Wiklander                 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
1513d3b0591SJens Wiklander             memset( p, 0, nblimbs * ciL );
1523d3b0591SJens Wiklander         }
1533d3b0591SJens Wiklander         else
1543d3b0591SJens Wiklander         {
1553d3b0591SJens Wiklander             p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL );
1563d3b0591SJens Wiklander             if( p == NULL )
1573d3b0591SJens Wiklander                 return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
158817466cbSJens Wiklander         }
159817466cbSJens Wiklander 
1603d3b0591SJens Wiklander         if( X->p != NULL )
1613d3b0591SJens Wiklander         {
1623d3b0591SJens Wiklander             memcpy( p, X->p, X->n * ciL );
1633d3b0591SJens Wiklander             mbedtls_mpi_zeroize( X->p, X->n );
1643d3b0591SJens Wiklander             if( X->use_mempool )
16518c5148dSJens Wiklander                 mempool_free( mbedtls_mpi_mempool, X->p);
1663d3b0591SJens Wiklander             else
1673d3b0591SJens Wiklander                 mbedtls_free( X->p );
1683d3b0591SJens Wiklander         }
16918c5148dSJens Wiklander 
17018c5148dSJens Wiklander         X->n = nblimbs;
1713d3b0591SJens Wiklander         X->p = p;
1723d3b0591SJens Wiklander     }
173817466cbSJens Wiklander 
174817466cbSJens Wiklander     return( 0 );
175817466cbSJens Wiklander }
176817466cbSJens Wiklander 
177817466cbSJens Wiklander /*
178817466cbSJens Wiklander  * Resize down as much as possible,
179817466cbSJens Wiklander  * while keeping at least the specified number of limbs
180817466cbSJens Wiklander  */
181817466cbSJens Wiklander int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
182817466cbSJens Wiklander {
183817466cbSJens Wiklander     mbedtls_mpi_uint *p;
184817466cbSJens Wiklander     size_t i;
1853d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
1863d3b0591SJens Wiklander 
1873d3b0591SJens Wiklander     if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
1883d3b0591SJens Wiklander         return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
189817466cbSJens Wiklander 
1905b25c76aSJerome Forissier     /* Actually resize up if there are currently fewer than nblimbs limbs. */
191817466cbSJens Wiklander     if( X->n <= nblimbs )
192817466cbSJens Wiklander         return( mbedtls_mpi_grow( X, nblimbs ) );
1935b25c76aSJerome Forissier     /* After this point, then X->n > nblimbs and in particular X->n > 0. */
194817466cbSJens Wiklander 
195817466cbSJens Wiklander     for( i = X->n - 1; i > 0; i-- )
196817466cbSJens Wiklander         if( X->p[i] != 0 )
197817466cbSJens Wiklander             break;
198817466cbSJens Wiklander     i++;
199817466cbSJens Wiklander 
200817466cbSJens Wiklander     if( i < nblimbs )
201817466cbSJens Wiklander         i = nblimbs;
202817466cbSJens Wiklander 
2033d3b0591SJens Wiklander     if( X->use_mempool )
2043d3b0591SJens Wiklander     {
205ed3fa831SJerome Forissier         p = mempool_alloc( mbedtls_mpi_mempool, i * ciL );
2063d3b0591SJens Wiklander         if( p == NULL )
20798bd5fe3SJens Wiklander             return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
208ed3fa831SJerome Forissier         memset( p, 0, i * ciL );
20998bd5fe3SJens Wiklander     }
2103d3b0591SJens Wiklander     else
2113d3b0591SJens Wiklander     {
212ed3fa831SJerome Forissier         p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL );
2133d3b0591SJens Wiklander         if( p == NULL )
2143d3b0591SJens Wiklander             return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
2153d3b0591SJens Wiklander     }
21618c5148dSJens Wiklander 
217817466cbSJens Wiklander     if( X->p != NULL )
218817466cbSJens Wiklander     {
219817466cbSJens Wiklander         memcpy( p, X->p, i * ciL );
220817466cbSJens Wiklander         mbedtls_mpi_zeroize( X->p, X->n );
2213d3b0591SJens Wiklander         if( X->use_mempool )
22218c5148dSJens Wiklander             mempool_free( mbedtls_mpi_mempool, X->p );
2233d3b0591SJens Wiklander         else
2243d3b0591SJens Wiklander             mbedtls_free( X->p );
225817466cbSJens Wiklander     }
226817466cbSJens Wiklander 
22718c5148dSJens Wiklander     X->n = i;
2283d3b0591SJens Wiklander     X->p = p;
229817466cbSJens Wiklander 
230817466cbSJens Wiklander     return( 0 );
231817466cbSJens Wiklander }
232817466cbSJens Wiklander 
2337901324dSJerome Forissier /* Resize X to have exactly n limbs and set it to 0. */
2347901324dSJerome Forissier static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs )
2357901324dSJerome Forissier {
2367901324dSJerome Forissier     if( limbs == 0 )
2377901324dSJerome Forissier     {
2387901324dSJerome Forissier         mbedtls_mpi_free( X );
2397901324dSJerome Forissier         return( 0 );
2407901324dSJerome Forissier     }
2417901324dSJerome Forissier     else if( X->n == limbs )
2427901324dSJerome Forissier     {
2437901324dSJerome Forissier         memset( X->p, 0, limbs * ciL );
2447901324dSJerome Forissier         X->s = 1;
2457901324dSJerome Forissier         return( 0 );
2467901324dSJerome Forissier     }
2477901324dSJerome Forissier     else
2487901324dSJerome Forissier     {
2497901324dSJerome Forissier         mbedtls_mpi_free( X );
2507901324dSJerome Forissier         return( mbedtls_mpi_grow( X, limbs ) );
2517901324dSJerome Forissier     }
2527901324dSJerome Forissier }
2537901324dSJerome Forissier 
254817466cbSJens Wiklander /*
2557901324dSJerome Forissier  * Copy the contents of Y into X.
2567901324dSJerome Forissier  *
2577901324dSJerome Forissier  * This function is not constant-time. Leading zeros in Y may be removed.
2587901324dSJerome Forissier  *
2597901324dSJerome Forissier  * Ensure that X does not shrink. This is not guaranteed by the public API,
2607901324dSJerome Forissier  * but some code in the bignum module relies on this property, for example
2617901324dSJerome Forissier  * in mbedtls_mpi_exp_mod().
262817466cbSJens Wiklander  */
263817466cbSJens Wiklander int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
264817466cbSJens Wiklander {
2653d3b0591SJens Wiklander     int ret = 0;
266817466cbSJens Wiklander     size_t i;
2673d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
2683d3b0591SJens Wiklander     MPI_VALIDATE_RET( Y != NULL );
269817466cbSJens Wiklander 
270817466cbSJens Wiklander     if( X == Y )
271817466cbSJens Wiklander         return( 0 );
272817466cbSJens Wiklander 
2735b25c76aSJerome Forissier     if( Y->n == 0 )
274817466cbSJens Wiklander     {
2757901324dSJerome Forissier         if( X->n != 0 )
2767901324dSJerome Forissier         {
2777901324dSJerome Forissier             X->s = 1;
2787901324dSJerome Forissier             memset( X->p, 0, X->n * ciL );
2797901324dSJerome Forissier         }
280817466cbSJens Wiklander         return( 0 );
281817466cbSJens Wiklander     }
282817466cbSJens Wiklander 
283817466cbSJens Wiklander     for( i = Y->n - 1; i > 0; i-- )
284817466cbSJens Wiklander         if( Y->p[i] != 0 )
285817466cbSJens Wiklander             break;
286817466cbSJens Wiklander     i++;
287817466cbSJens Wiklander 
288817466cbSJens Wiklander     X->s = Y->s;
289817466cbSJens Wiklander 
2903d3b0591SJens Wiklander     if( X->n < i )
2913d3b0591SJens Wiklander     {
292817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) );
2933d3b0591SJens Wiklander     }
2943d3b0591SJens Wiklander     else
2953d3b0591SJens Wiklander     {
2963d3b0591SJens Wiklander         memset( X->p + i, 0, ( X->n - i ) * ciL );
2973d3b0591SJens Wiklander     }
298817466cbSJens Wiklander 
299817466cbSJens Wiklander     memcpy( X->p, Y->p, i * ciL );
300817466cbSJens Wiklander 
301817466cbSJens Wiklander cleanup:
302817466cbSJens Wiklander 
303817466cbSJens Wiklander     return( ret );
304817466cbSJens Wiklander }
305817466cbSJens Wiklander 
306817466cbSJens Wiklander /*
307817466cbSJens Wiklander  * Swap the contents of X and Y
308817466cbSJens Wiklander  */
309817466cbSJens Wiklander void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )
310817466cbSJens Wiklander {
311817466cbSJens Wiklander     mbedtls_mpi T;
3123d3b0591SJens Wiklander     MPI_VALIDATE( X != NULL );
3133d3b0591SJens Wiklander     MPI_VALIDATE( Y != NULL );
314817466cbSJens Wiklander 
315817466cbSJens Wiklander     memcpy( &T,  X, sizeof( mbedtls_mpi ) );
316817466cbSJens Wiklander     memcpy(  X,  Y, sizeof( mbedtls_mpi ) );
317817466cbSJens Wiklander     memcpy(  Y, &T, sizeof( mbedtls_mpi ) );
318817466cbSJens Wiklander }
319817466cbSJens Wiklander 
320817466cbSJens Wiklander /*
321817466cbSJens Wiklander  * Set value from integer
322817466cbSJens Wiklander  */
323817466cbSJens Wiklander int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
324817466cbSJens Wiklander {
32511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3263d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
327817466cbSJens Wiklander 
328817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
329817466cbSJens Wiklander     memset( X->p, 0, X->n * ciL );
330817466cbSJens Wiklander 
331817466cbSJens Wiklander     X->p[0] = ( z < 0 ) ? -z : z;
332817466cbSJens Wiklander     X->s    = ( z < 0 ) ? -1 : 1;
333817466cbSJens Wiklander 
334817466cbSJens Wiklander cleanup:
335817466cbSJens Wiklander 
336817466cbSJens Wiklander     return( ret );
337817466cbSJens Wiklander }
338817466cbSJens Wiklander 
339817466cbSJens Wiklander /*
340817466cbSJens Wiklander  * Get a specific bit
341817466cbSJens Wiklander  */
342817466cbSJens Wiklander int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
343817466cbSJens Wiklander {
3443d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
3453d3b0591SJens Wiklander 
346817466cbSJens Wiklander     if( X->n * biL <= pos )
347817466cbSJens Wiklander         return( 0 );
348817466cbSJens Wiklander 
349817466cbSJens Wiklander     return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
350817466cbSJens Wiklander }
351817466cbSJens Wiklander 
3523d3b0591SJens Wiklander /* Get a specific byte, without range checks. */
3533d3b0591SJens Wiklander #define GET_BYTE( X, i )                                \
3543d3b0591SJens Wiklander     ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
3553d3b0591SJens Wiklander 
356817466cbSJens Wiklander /*
357817466cbSJens Wiklander  * Set a bit to a specific value of 0 or 1
358817466cbSJens Wiklander  */
359817466cbSJens Wiklander int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val )
360817466cbSJens Wiklander {
361817466cbSJens Wiklander     int ret = 0;
362817466cbSJens Wiklander     size_t off = pos / biL;
363817466cbSJens Wiklander     size_t idx = pos % biL;
3643d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
365817466cbSJens Wiklander 
366817466cbSJens Wiklander     if( val != 0 && val != 1 )
367817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
368817466cbSJens Wiklander 
369817466cbSJens Wiklander     if( X->n * biL <= pos )
370817466cbSJens Wiklander     {
371817466cbSJens Wiklander         if( val == 0 )
372817466cbSJens Wiklander             return( 0 );
373817466cbSJens Wiklander 
374817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) );
375817466cbSJens Wiklander     }
376817466cbSJens Wiklander 
377817466cbSJens Wiklander     X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx );
378817466cbSJens Wiklander     X->p[off] |= (mbedtls_mpi_uint) val << idx;
379817466cbSJens Wiklander 
380817466cbSJens Wiklander cleanup:
381817466cbSJens Wiklander 
382817466cbSJens Wiklander     return( ret );
383817466cbSJens Wiklander }
384817466cbSJens Wiklander 
385817466cbSJens Wiklander /*
386817466cbSJens Wiklander  * Return the number of less significant zero-bits
387817466cbSJens Wiklander  */
388817466cbSJens Wiklander size_t mbedtls_mpi_lsb( const mbedtls_mpi *X )
389817466cbSJens Wiklander {
390817466cbSJens Wiklander     size_t i, j, count = 0;
3913d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 );
392817466cbSJens Wiklander 
393817466cbSJens Wiklander     for( i = 0; i < X->n; i++ )
394817466cbSJens Wiklander         for( j = 0; j < biL; j++, count++ )
395817466cbSJens Wiklander             if( ( ( X->p[i] >> j ) & 1 ) != 0 )
396817466cbSJens Wiklander                 return( count );
397817466cbSJens Wiklander 
398817466cbSJens Wiklander     return( 0 );
399817466cbSJens Wiklander }
400817466cbSJens Wiklander 
401817466cbSJens Wiklander /*
402817466cbSJens Wiklander  * Count leading zero bits in a given integer
403817466cbSJens Wiklander  */
404817466cbSJens Wiklander static size_t mbedtls_clz( const mbedtls_mpi_uint x )
405817466cbSJens Wiklander {
406817466cbSJens Wiklander     size_t j;
407817466cbSJens Wiklander     mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
408817466cbSJens Wiklander 
409817466cbSJens Wiklander     for( j = 0; j < biL; j++ )
410817466cbSJens Wiklander     {
411817466cbSJens Wiklander         if( x & mask ) break;
412817466cbSJens Wiklander 
413817466cbSJens Wiklander         mask >>= 1;
414817466cbSJens Wiklander     }
415817466cbSJens Wiklander 
416817466cbSJens Wiklander     return j;
417817466cbSJens Wiklander }
418817466cbSJens Wiklander 
419817466cbSJens Wiklander /*
420817466cbSJens Wiklander  * Return the number of bits
421817466cbSJens Wiklander  */
422817466cbSJens Wiklander size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X )
423817466cbSJens Wiklander {
424817466cbSJens Wiklander     size_t i, j;
425817466cbSJens Wiklander 
426817466cbSJens Wiklander     if( X->n == 0 )
427817466cbSJens Wiklander         return( 0 );
428817466cbSJens Wiklander 
429817466cbSJens Wiklander     for( i = X->n - 1; i > 0; i-- )
430817466cbSJens Wiklander         if( X->p[i] != 0 )
431817466cbSJens Wiklander             break;
432817466cbSJens Wiklander 
433817466cbSJens Wiklander     j = biL - mbedtls_clz( X->p[i] );
434817466cbSJens Wiklander 
435817466cbSJens Wiklander     return( ( i * biL ) + j );
436817466cbSJens Wiklander }
437817466cbSJens Wiklander 
438817466cbSJens Wiklander /*
439817466cbSJens Wiklander  * Return the total size in bytes
440817466cbSJens Wiklander  */
441817466cbSJens Wiklander size_t mbedtls_mpi_size( const mbedtls_mpi *X )
442817466cbSJens Wiklander {
443817466cbSJens Wiklander     return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 );
444817466cbSJens Wiklander }
445817466cbSJens Wiklander 
446817466cbSJens Wiklander /*
447817466cbSJens Wiklander  * Convert an ASCII character to digit value
448817466cbSJens Wiklander  */
449817466cbSJens Wiklander static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
450817466cbSJens Wiklander {
451817466cbSJens Wiklander     *d = 255;
452817466cbSJens Wiklander 
453817466cbSJens Wiklander     if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
454817466cbSJens Wiklander     if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
455817466cbSJens Wiklander     if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
456817466cbSJens Wiklander 
457817466cbSJens Wiklander     if( *d >= (mbedtls_mpi_uint) radix )
458817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_INVALID_CHARACTER );
459817466cbSJens Wiklander 
460817466cbSJens Wiklander     return( 0 );
461817466cbSJens Wiklander }
462817466cbSJens Wiklander 
463817466cbSJens Wiklander /*
464817466cbSJens Wiklander  * Import from an ASCII string
465817466cbSJens Wiklander  */
466817466cbSJens Wiklander int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
467817466cbSJens Wiklander {
46811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
469817466cbSJens Wiklander     size_t i, j, slen, n;
4707901324dSJerome Forissier     int sign = 1;
471817466cbSJens Wiklander     mbedtls_mpi_uint d;
472817466cbSJens Wiklander     mbedtls_mpi T;
4733d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
4743d3b0591SJens Wiklander     MPI_VALIDATE_RET( s != NULL );
475817466cbSJens Wiklander 
476817466cbSJens Wiklander     if( radix < 2 || radix > 16 )
477817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
478817466cbSJens Wiklander 
47998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &T );
480817466cbSJens Wiklander 
4817901324dSJerome Forissier     if( s[0] == 0 )
4827901324dSJerome Forissier     {
4837901324dSJerome Forissier         mbedtls_mpi_free( X );
4847901324dSJerome Forissier         return( 0 );
4857901324dSJerome Forissier     }
4867901324dSJerome Forissier 
4877901324dSJerome Forissier     if( s[0] == '-' )
4887901324dSJerome Forissier     {
4897901324dSJerome Forissier         ++s;
4907901324dSJerome Forissier         sign = -1;
4917901324dSJerome Forissier     }
4927901324dSJerome Forissier 
493817466cbSJens Wiklander     slen = strlen( s );
494817466cbSJens Wiklander 
495817466cbSJens Wiklander     if( radix == 16 )
496817466cbSJens Wiklander     {
497817466cbSJens Wiklander         if( slen > MPI_SIZE_T_MAX >> 2 )
498817466cbSJens Wiklander             return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
499817466cbSJens Wiklander 
500817466cbSJens Wiklander         n = BITS_TO_LIMBS( slen << 2 );
501817466cbSJens Wiklander 
502817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) );
503817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
504817466cbSJens Wiklander 
505817466cbSJens Wiklander         for( i = slen, j = 0; i > 0; i--, j++ )
506817466cbSJens Wiklander         {
507817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) );
508817466cbSJens Wiklander             X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 );
509817466cbSJens Wiklander         }
510817466cbSJens Wiklander     }
511817466cbSJens Wiklander     else
512817466cbSJens Wiklander     {
513817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
514817466cbSJens Wiklander 
515817466cbSJens Wiklander         for( i = 0; i < slen; i++ )
516817466cbSJens Wiklander         {
517817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
518817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) );
519817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) );
520817466cbSJens Wiklander         }
521817466cbSJens Wiklander     }
5227901324dSJerome Forissier 
5237901324dSJerome Forissier     if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 )
5247901324dSJerome Forissier         X->s = -1;
525817466cbSJens Wiklander 
526817466cbSJens Wiklander cleanup:
527817466cbSJens Wiklander 
528817466cbSJens Wiklander     mbedtls_mpi_free( &T );
529817466cbSJens Wiklander 
530817466cbSJens Wiklander     return( ret );
531817466cbSJens Wiklander }
532817466cbSJens Wiklander 
533817466cbSJens Wiklander /*
5345b25c76aSJerome Forissier  * Helper to write the digits high-order first.
535817466cbSJens Wiklander  */
5365b25c76aSJerome Forissier static int mpi_write_hlp( mbedtls_mpi *X, int radix,
5375b25c76aSJerome Forissier                           char **p, const size_t buflen )
538817466cbSJens Wiklander {
53911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
540817466cbSJens Wiklander     mbedtls_mpi_uint r;
5415b25c76aSJerome Forissier     size_t length = 0;
5425b25c76aSJerome Forissier     char *p_end = *p + buflen;
543817466cbSJens Wiklander 
5445b25c76aSJerome Forissier     do
5455b25c76aSJerome Forissier     {
5465b25c76aSJerome Forissier         if( length >= buflen )
5475b25c76aSJerome Forissier         {
5485b25c76aSJerome Forissier             return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
5495b25c76aSJerome Forissier         }
550817466cbSJens Wiklander 
551817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) );
552817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) );
5535b25c76aSJerome Forissier         /*
5545b25c76aSJerome Forissier          * Write the residue in the current position, as an ASCII character.
5555b25c76aSJerome Forissier          */
5565b25c76aSJerome Forissier         if( r < 0xA )
5575b25c76aSJerome Forissier             *(--p_end) = (char)( '0' + r );
558817466cbSJens Wiklander         else
5595b25c76aSJerome Forissier             *(--p_end) = (char)( 'A' + ( r - 0xA ) );
5605b25c76aSJerome Forissier 
5615b25c76aSJerome Forissier         length++;
5625b25c76aSJerome Forissier     } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 );
5635b25c76aSJerome Forissier 
5645b25c76aSJerome Forissier     memmove( *p, p_end, length );
5655b25c76aSJerome Forissier     *p += length;
566817466cbSJens Wiklander 
567817466cbSJens Wiklander cleanup:
568817466cbSJens Wiklander 
569817466cbSJens Wiklander     return( ret );
570817466cbSJens Wiklander }
571817466cbSJens Wiklander 
572817466cbSJens Wiklander /*
573817466cbSJens Wiklander  * Export into an ASCII string
574817466cbSJens Wiklander  */
575817466cbSJens Wiklander int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix,
576817466cbSJens Wiklander                               char *buf, size_t buflen, size_t *olen )
577817466cbSJens Wiklander {
578817466cbSJens Wiklander     int ret = 0;
579817466cbSJens Wiklander     size_t n;
580817466cbSJens Wiklander     char *p;
581817466cbSJens Wiklander     mbedtls_mpi T;
5823d3b0591SJens Wiklander     MPI_VALIDATE_RET( X    != NULL );
5833d3b0591SJens Wiklander     MPI_VALIDATE_RET( olen != NULL );
5843d3b0591SJens Wiklander     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
585817466cbSJens Wiklander 
586817466cbSJens Wiklander     if( radix < 2 || radix > 16 )
587817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
588817466cbSJens Wiklander 
5895b25c76aSJerome Forissier     n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */
5905b25c76aSJerome Forissier     if( radix >=  4 ) n >>= 1;   /* Number of 4-adic digits necessary to present
5915b25c76aSJerome Forissier                                   * `n`. If radix > 4, this might be a strict
5925b25c76aSJerome Forissier                                   * overapproximation of the number of
5935b25c76aSJerome Forissier                                   * radix-adic digits needed to present `n`. */
5945b25c76aSJerome Forissier     if( radix >= 16 ) n >>= 1;   /* Number of hexadecimal digits necessary to
5955b25c76aSJerome Forissier                                   * present `n`. */
5965b25c76aSJerome Forissier 
5975b25c76aSJerome Forissier     n += 1; /* Terminating null byte */
5985b25c76aSJerome Forissier     n += 1; /* Compensate for the divisions above, which round down `n`
5995b25c76aSJerome Forissier              * in case it's not even. */
6005b25c76aSJerome Forissier     n += 1; /* Potential '-'-sign. */
6015b25c76aSJerome Forissier     n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing,
6025b25c76aSJerome Forissier                      * which always uses an even number of hex-digits. */
603817466cbSJens Wiklander 
604817466cbSJens Wiklander     if( buflen < n )
605817466cbSJens Wiklander     {
606817466cbSJens Wiklander         *olen = n;
607817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
608817466cbSJens Wiklander     }
609817466cbSJens Wiklander 
610817466cbSJens Wiklander     p = buf;
61198bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &T );
612817466cbSJens Wiklander 
613817466cbSJens Wiklander     if( X->s == -1 )
6145b25c76aSJerome Forissier     {
615817466cbSJens Wiklander         *p++ = '-';
6165b25c76aSJerome Forissier         buflen--;
6175b25c76aSJerome Forissier     }
618817466cbSJens Wiklander 
619817466cbSJens Wiklander     if( radix == 16 )
620817466cbSJens Wiklander     {
621817466cbSJens Wiklander         int c;
622817466cbSJens Wiklander         size_t i, j, k;
623817466cbSJens Wiklander 
624817466cbSJens Wiklander         for( i = X->n, k = 0; i > 0; i-- )
625817466cbSJens Wiklander         {
626817466cbSJens Wiklander             for( j = ciL; j > 0; j-- )
627817466cbSJens Wiklander             {
628817466cbSJens Wiklander                 c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF;
629817466cbSJens Wiklander 
630817466cbSJens Wiklander                 if( c == 0 && k == 0 && ( i + j ) != 2 )
631817466cbSJens Wiklander                     continue;
632817466cbSJens Wiklander 
633817466cbSJens Wiklander                 *(p++) = "0123456789ABCDEF" [c / 16];
634817466cbSJens Wiklander                 *(p++) = "0123456789ABCDEF" [c % 16];
635817466cbSJens Wiklander                 k = 1;
636817466cbSJens Wiklander             }
637817466cbSJens Wiklander         }
638817466cbSJens Wiklander     }
639817466cbSJens Wiklander     else
640817466cbSJens Wiklander     {
641817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) );
642817466cbSJens Wiklander 
643817466cbSJens Wiklander         if( T.s == -1 )
644817466cbSJens Wiklander             T.s = 1;
645817466cbSJens Wiklander 
6465b25c76aSJerome Forissier         MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) );
647817466cbSJens Wiklander     }
648817466cbSJens Wiklander 
649817466cbSJens Wiklander     *p++ = '\0';
650817466cbSJens Wiklander     *olen = p - buf;
651817466cbSJens Wiklander 
652817466cbSJens Wiklander cleanup:
653817466cbSJens Wiklander 
654817466cbSJens Wiklander     mbedtls_mpi_free( &T );
655817466cbSJens Wiklander 
656817466cbSJens Wiklander     return( ret );
657817466cbSJens Wiklander }
658817466cbSJens Wiklander 
659817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
660817466cbSJens Wiklander /*
661817466cbSJens Wiklander  * Read X from an opened file
662817466cbSJens Wiklander  */
663817466cbSJens Wiklander int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
664817466cbSJens Wiklander {
665817466cbSJens Wiklander     mbedtls_mpi_uint d;
666817466cbSJens Wiklander     size_t slen;
667817466cbSJens Wiklander     char *p;
668817466cbSJens Wiklander     /*
669817466cbSJens Wiklander      * Buffer should have space for (short) label and decimal formatted MPI,
670817466cbSJens Wiklander      * newline characters and '\0'
671817466cbSJens Wiklander      */
672817466cbSJens Wiklander     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
673817466cbSJens Wiklander 
6743d3b0591SJens Wiklander     MPI_VALIDATE_RET( X   != NULL );
6753d3b0591SJens Wiklander     MPI_VALIDATE_RET( fin != NULL );
6763d3b0591SJens Wiklander 
6773d3b0591SJens Wiklander     if( radix < 2 || radix > 16 )
6783d3b0591SJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
6793d3b0591SJens Wiklander 
680817466cbSJens Wiklander     memset( s, 0, sizeof( s ) );
681817466cbSJens Wiklander     if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
682817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
683817466cbSJens Wiklander 
684817466cbSJens Wiklander     slen = strlen( s );
685817466cbSJens Wiklander     if( slen == sizeof( s ) - 2 )
686817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
687817466cbSJens Wiklander 
688817466cbSJens Wiklander     if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
689817466cbSJens Wiklander     if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
690817466cbSJens Wiklander 
691817466cbSJens Wiklander     p = s + slen;
692817466cbSJens Wiklander     while( p-- > s )
693817466cbSJens Wiklander         if( mpi_get_digit( &d, radix, *p ) != 0 )
694817466cbSJens Wiklander             break;
695817466cbSJens Wiklander 
696817466cbSJens Wiklander     return( mbedtls_mpi_read_string( X, radix, p + 1 ) );
697817466cbSJens Wiklander }
698817466cbSJens Wiklander 
699817466cbSJens Wiklander /*
700817466cbSJens Wiklander  * Write X into an opened file (or stdout if fout == NULL)
701817466cbSJens Wiklander  */
702817466cbSJens Wiklander int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
703817466cbSJens Wiklander {
70411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
705817466cbSJens Wiklander     size_t n, slen, plen;
706817466cbSJens Wiklander     /*
707817466cbSJens Wiklander      * Buffer should have space for (short) label and decimal formatted MPI,
708817466cbSJens Wiklander      * newline characters and '\0'
709817466cbSJens Wiklander      */
710817466cbSJens Wiklander     char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ];
7113d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
7123d3b0591SJens Wiklander 
7133d3b0591SJens Wiklander     if( radix < 2 || radix > 16 )
7143d3b0591SJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
715817466cbSJens Wiklander 
716817466cbSJens Wiklander     memset( s, 0, sizeof( s ) );
717817466cbSJens Wiklander 
718817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) );
719817466cbSJens Wiklander 
720817466cbSJens Wiklander     if( p == NULL ) p = "";
721817466cbSJens Wiklander 
722817466cbSJens Wiklander     plen = strlen( p );
723817466cbSJens Wiklander     slen = strlen( s );
724817466cbSJens Wiklander     s[slen++] = '\r';
725817466cbSJens Wiklander     s[slen++] = '\n';
726817466cbSJens Wiklander 
727817466cbSJens Wiklander     if( fout != NULL )
728817466cbSJens Wiklander     {
729817466cbSJens Wiklander         if( fwrite( p, 1, plen, fout ) != plen ||
730817466cbSJens Wiklander             fwrite( s, 1, slen, fout ) != slen )
731817466cbSJens Wiklander             return( MBEDTLS_ERR_MPI_FILE_IO_ERROR );
732817466cbSJens Wiklander     }
733817466cbSJens Wiklander     else
734817466cbSJens Wiklander         mbedtls_printf( "%s%s", p, s );
735817466cbSJens Wiklander 
736817466cbSJens Wiklander cleanup:
737817466cbSJens Wiklander 
738817466cbSJens Wiklander     return( ret );
739817466cbSJens Wiklander }
740817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
741817466cbSJens Wiklander 
7425b25c76aSJerome Forissier 
7435b25c76aSJerome Forissier /* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
7445b25c76aSJerome Forissier  * into the storage form used by mbedtls_mpi. */
7455b25c76aSJerome Forissier 
7465b25c76aSJerome Forissier static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x )
7475b25c76aSJerome Forissier {
7485b25c76aSJerome Forissier     uint8_t i;
7495b25c76aSJerome Forissier     unsigned char *x_ptr;
7505b25c76aSJerome Forissier     mbedtls_mpi_uint tmp = 0;
7515b25c76aSJerome Forissier 
7525b25c76aSJerome Forissier     for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ )
7535b25c76aSJerome Forissier     {
7545b25c76aSJerome Forissier         tmp <<= CHAR_BIT;
7555b25c76aSJerome Forissier         tmp |= (mbedtls_mpi_uint) *x_ptr;
7565b25c76aSJerome Forissier     }
7575b25c76aSJerome Forissier 
7585b25c76aSJerome Forissier     return( tmp );
7595b25c76aSJerome Forissier }
7605b25c76aSJerome Forissier 
7615b25c76aSJerome Forissier static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x )
7625b25c76aSJerome Forissier {
7635b25c76aSJerome Forissier #if defined(__BYTE_ORDER__)
7645b25c76aSJerome Forissier 
7655b25c76aSJerome Forissier /* Nothing to do on bigendian systems. */
7665b25c76aSJerome Forissier #if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ )
7675b25c76aSJerome Forissier     return( x );
7685b25c76aSJerome Forissier #endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */
7695b25c76aSJerome Forissier 
7705b25c76aSJerome Forissier #if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
7715b25c76aSJerome Forissier 
7725b25c76aSJerome Forissier /* For GCC and Clang, have builtins for byte swapping. */
7735b25c76aSJerome Forissier #if defined(__GNUC__) && defined(__GNUC_PREREQ)
7745b25c76aSJerome Forissier #if __GNUC_PREREQ(4,3)
7755b25c76aSJerome Forissier #define have_bswap
7765b25c76aSJerome Forissier #endif
7775b25c76aSJerome Forissier #endif
7785b25c76aSJerome Forissier 
7795b25c76aSJerome Forissier #if defined(__clang__) && defined(__has_builtin)
7805b25c76aSJerome Forissier #if __has_builtin(__builtin_bswap32)  &&                 \
7815b25c76aSJerome Forissier     __has_builtin(__builtin_bswap64)
7825b25c76aSJerome Forissier #define have_bswap
7835b25c76aSJerome Forissier #endif
7845b25c76aSJerome Forissier #endif
7855b25c76aSJerome Forissier 
7865b25c76aSJerome Forissier #if defined(have_bswap)
7875b25c76aSJerome Forissier     /* The compiler is hopefully able to statically evaluate this! */
7885b25c76aSJerome Forissier     switch( sizeof(mbedtls_mpi_uint) )
7895b25c76aSJerome Forissier     {
7905b25c76aSJerome Forissier         case 4:
7915b25c76aSJerome Forissier             return( __builtin_bswap32(x) );
7925b25c76aSJerome Forissier         case 8:
7935b25c76aSJerome Forissier             return( __builtin_bswap64(x) );
7945b25c76aSJerome Forissier     }
7955b25c76aSJerome Forissier #endif
7965b25c76aSJerome Forissier #endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
7975b25c76aSJerome Forissier #endif /* __BYTE_ORDER__ */
7985b25c76aSJerome Forissier 
7995b25c76aSJerome Forissier     /* Fall back to C-based reordering if we don't know the byte order
8005b25c76aSJerome Forissier      * or we couldn't use a compiler-specific builtin. */
8015b25c76aSJerome Forissier     return( mpi_uint_bigendian_to_host_c( x ) );
8025b25c76aSJerome Forissier }
8035b25c76aSJerome Forissier 
8045b25c76aSJerome Forissier static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
8055b25c76aSJerome Forissier {
8065b25c76aSJerome Forissier     mbedtls_mpi_uint *cur_limb_left;
8075b25c76aSJerome Forissier     mbedtls_mpi_uint *cur_limb_right;
8085b25c76aSJerome Forissier     if( limbs == 0 )
8095b25c76aSJerome Forissier         return;
8105b25c76aSJerome Forissier 
8115b25c76aSJerome Forissier     /*
8125b25c76aSJerome Forissier      * Traverse limbs and
8135b25c76aSJerome Forissier      * - adapt byte-order in each limb
8145b25c76aSJerome Forissier      * - swap the limbs themselves.
8155b25c76aSJerome Forissier      * For that, simultaneously traverse the limbs from left to right
8165b25c76aSJerome Forissier      * and from right to left, as long as the left index is not bigger
8175b25c76aSJerome Forissier      * than the right index (it's not a problem if limbs is odd and the
8185b25c76aSJerome Forissier      * indices coincide in the last iteration).
8195b25c76aSJerome Forissier      */
8205b25c76aSJerome Forissier     for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 );
8215b25c76aSJerome Forissier          cur_limb_left <= cur_limb_right;
8225b25c76aSJerome Forissier          cur_limb_left++, cur_limb_right-- )
8235b25c76aSJerome Forissier     {
8245b25c76aSJerome Forissier         mbedtls_mpi_uint tmp;
8255b25c76aSJerome Forissier         /* Note that if cur_limb_left == cur_limb_right,
8265b25c76aSJerome Forissier          * this code effectively swaps the bytes only once. */
8275b25c76aSJerome Forissier         tmp             = mpi_uint_bigendian_to_host( *cur_limb_left  );
8285b25c76aSJerome Forissier         *cur_limb_left  = mpi_uint_bigendian_to_host( *cur_limb_right );
8295b25c76aSJerome Forissier         *cur_limb_right = tmp;
8305b25c76aSJerome Forissier     }
8315b25c76aSJerome Forissier }
8325b25c76aSJerome Forissier 
833817466cbSJens Wiklander /*
83411fa71b9SJerome Forissier  * Import X from unsigned binary data, little endian
83511fa71b9SJerome Forissier  */
83611fa71b9SJerome Forissier int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
83711fa71b9SJerome Forissier                                 const unsigned char *buf, size_t buflen )
83811fa71b9SJerome Forissier {
83911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
84011fa71b9SJerome Forissier     size_t i;
84111fa71b9SJerome Forissier     size_t const limbs = CHARS_TO_LIMBS( buflen );
84211fa71b9SJerome Forissier 
84311fa71b9SJerome Forissier     /* Ensure that target MPI has exactly the necessary number of limbs */
8447901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
84511fa71b9SJerome Forissier 
84611fa71b9SJerome Forissier     for( i = 0; i < buflen; i++ )
84711fa71b9SJerome Forissier         X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3);
84811fa71b9SJerome Forissier 
84911fa71b9SJerome Forissier cleanup:
85011fa71b9SJerome Forissier 
85111fa71b9SJerome Forissier     /*
85211fa71b9SJerome Forissier      * This function is also used to import keys. However, wiping the buffers
85311fa71b9SJerome Forissier      * upon failure is not necessary because failure only can happen before any
85411fa71b9SJerome Forissier      * input is copied.
85511fa71b9SJerome Forissier      */
85611fa71b9SJerome Forissier     return( ret );
85711fa71b9SJerome Forissier }
85811fa71b9SJerome Forissier 
85911fa71b9SJerome Forissier /*
860817466cbSJens Wiklander  * Import X from unsigned binary data, big endian
861817466cbSJens Wiklander  */
862817466cbSJens Wiklander int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
863817466cbSJens Wiklander {
86411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
8653d3b0591SJens Wiklander     size_t const limbs    = CHARS_TO_LIMBS( buflen );
8665b25c76aSJerome Forissier     size_t const overhead = ( limbs * ciL ) - buflen;
8675b25c76aSJerome Forissier     unsigned char *Xp;
868817466cbSJens Wiklander 
8693d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
8703d3b0591SJens Wiklander     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
871817466cbSJens Wiklander 
8723d3b0591SJens Wiklander     /* Ensure that target MPI has exactly the necessary number of limbs */
8737901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
8742976273fSJens Wiklander 
8757901324dSJerome Forissier     /* Avoid calling `memcpy` with NULL source or destination argument,
8765b25c76aSJerome Forissier      * even if buflen is 0. */
8777901324dSJerome Forissier     if( buflen != 0 )
8785b25c76aSJerome Forissier     {
8795b25c76aSJerome Forissier         Xp = (unsigned char*) X->p;
8805b25c76aSJerome Forissier         memcpy( Xp + overhead, buf, buflen );
8815b25c76aSJerome Forissier 
8825b25c76aSJerome Forissier         mpi_bigendian_to_host( X->p, limbs );
8835b25c76aSJerome Forissier     }
884817466cbSJens Wiklander 
885817466cbSJens Wiklander cleanup:
886817466cbSJens Wiklander 
88711fa71b9SJerome Forissier     /*
88811fa71b9SJerome Forissier      * This function is also used to import keys. However, wiping the buffers
88911fa71b9SJerome Forissier      * upon failure is not necessary because failure only can happen before any
89011fa71b9SJerome Forissier      * input is copied.
89111fa71b9SJerome Forissier      */
892817466cbSJens Wiklander     return( ret );
893817466cbSJens Wiklander }
894817466cbSJens Wiklander 
895817466cbSJens Wiklander /*
89611fa71b9SJerome Forissier  * Export X into unsigned binary data, little endian
89711fa71b9SJerome Forissier  */
89811fa71b9SJerome Forissier int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X,
89911fa71b9SJerome Forissier                                  unsigned char *buf, size_t buflen )
90011fa71b9SJerome Forissier {
90111fa71b9SJerome Forissier     size_t stored_bytes = X->n * ciL;
90211fa71b9SJerome Forissier     size_t bytes_to_copy;
90311fa71b9SJerome Forissier     size_t i;
90411fa71b9SJerome Forissier 
90511fa71b9SJerome Forissier     if( stored_bytes < buflen )
90611fa71b9SJerome Forissier     {
90711fa71b9SJerome Forissier         bytes_to_copy = stored_bytes;
90811fa71b9SJerome Forissier     }
90911fa71b9SJerome Forissier     else
91011fa71b9SJerome Forissier     {
91111fa71b9SJerome Forissier         bytes_to_copy = buflen;
91211fa71b9SJerome Forissier 
91311fa71b9SJerome Forissier         /* The output buffer is smaller than the allocated size of X.
91411fa71b9SJerome Forissier          * However X may fit if its leading bytes are zero. */
91511fa71b9SJerome Forissier         for( i = bytes_to_copy; i < stored_bytes; i++ )
91611fa71b9SJerome Forissier         {
91711fa71b9SJerome Forissier             if( GET_BYTE( X, i ) != 0 )
91811fa71b9SJerome Forissier                 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
91911fa71b9SJerome Forissier         }
92011fa71b9SJerome Forissier     }
92111fa71b9SJerome Forissier 
92211fa71b9SJerome Forissier     for( i = 0; i < bytes_to_copy; i++ )
92311fa71b9SJerome Forissier         buf[i] = GET_BYTE( X, i );
92411fa71b9SJerome Forissier 
92511fa71b9SJerome Forissier     if( stored_bytes < buflen )
92611fa71b9SJerome Forissier     {
92711fa71b9SJerome Forissier         /* Write trailing 0 bytes */
92811fa71b9SJerome Forissier         memset( buf + stored_bytes, 0, buflen - stored_bytes );
92911fa71b9SJerome Forissier     }
93011fa71b9SJerome Forissier 
93111fa71b9SJerome Forissier     return( 0 );
93211fa71b9SJerome Forissier }
93311fa71b9SJerome Forissier 
93411fa71b9SJerome Forissier /*
935817466cbSJens Wiklander  * Export X into unsigned binary data, big endian
936817466cbSJens Wiklander  */
9373d3b0591SJens Wiklander int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
9383d3b0591SJens Wiklander                               unsigned char *buf, size_t buflen )
939817466cbSJens Wiklander {
9403d3b0591SJens Wiklander     size_t stored_bytes;
9413d3b0591SJens Wiklander     size_t bytes_to_copy;
9423d3b0591SJens Wiklander     unsigned char *p;
9433d3b0591SJens Wiklander     size_t i;
944817466cbSJens Wiklander 
9453d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
9463d3b0591SJens Wiklander     MPI_VALIDATE_RET( buflen == 0 || buf != NULL );
947817466cbSJens Wiklander 
9483d3b0591SJens Wiklander     stored_bytes = X->n * ciL;
9493d3b0591SJens Wiklander 
9503d3b0591SJens Wiklander     if( stored_bytes < buflen )
9513d3b0591SJens Wiklander     {
9523d3b0591SJens Wiklander         /* There is enough space in the output buffer. Write initial
9533d3b0591SJens Wiklander          * null bytes and record the position at which to start
9543d3b0591SJens Wiklander          * writing the significant bytes. In this case, the execution
9553d3b0591SJens Wiklander          * trace of this function does not depend on the value of the
9563d3b0591SJens Wiklander          * number. */
9573d3b0591SJens Wiklander         bytes_to_copy = stored_bytes;
9583d3b0591SJens Wiklander         p = buf + buflen - stored_bytes;
9593d3b0591SJens Wiklander         memset( buf, 0, buflen - stored_bytes );
9603d3b0591SJens Wiklander     }
9613d3b0591SJens Wiklander     else
9623d3b0591SJens Wiklander     {
9633d3b0591SJens Wiklander         /* The output buffer is smaller than the allocated size of X.
9643d3b0591SJens Wiklander          * However X may fit if its leading bytes are zero. */
9653d3b0591SJens Wiklander         bytes_to_copy = buflen;
9663d3b0591SJens Wiklander         p = buf;
9673d3b0591SJens Wiklander         for( i = bytes_to_copy; i < stored_bytes; i++ )
9683d3b0591SJens Wiklander         {
9693d3b0591SJens Wiklander             if( GET_BYTE( X, i ) != 0 )
970817466cbSJens Wiklander                 return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
9713d3b0591SJens Wiklander         }
9723d3b0591SJens Wiklander     }
973817466cbSJens Wiklander 
9743d3b0591SJens Wiklander     for( i = 0; i < bytes_to_copy; i++ )
9753d3b0591SJens Wiklander         p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
976817466cbSJens Wiklander 
977817466cbSJens Wiklander     return( 0 );
978817466cbSJens Wiklander }
979817466cbSJens Wiklander 
980817466cbSJens Wiklander /*
981817466cbSJens Wiklander  * Left-shift: X <<= count
982817466cbSJens Wiklander  */
983817466cbSJens Wiklander int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
984817466cbSJens Wiklander {
98511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
986817466cbSJens Wiklander     size_t i, v0, t1;
987817466cbSJens Wiklander     mbedtls_mpi_uint r0 = 0, r1;
9883d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
989817466cbSJens Wiklander 
990817466cbSJens Wiklander     v0 = count / (biL    );
991817466cbSJens Wiklander     t1 = count & (biL - 1);
992817466cbSJens Wiklander 
993817466cbSJens Wiklander     i = mbedtls_mpi_bitlen( X ) + count;
994817466cbSJens Wiklander 
995817466cbSJens Wiklander     if( X->n * biL < i )
996817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) );
997817466cbSJens Wiklander 
998817466cbSJens Wiklander     ret = 0;
999817466cbSJens Wiklander 
1000817466cbSJens Wiklander     /*
1001817466cbSJens Wiklander      * shift by count / limb_size
1002817466cbSJens Wiklander      */
1003817466cbSJens Wiklander     if( v0 > 0 )
1004817466cbSJens Wiklander     {
1005817466cbSJens Wiklander         for( i = X->n; i > v0; i-- )
1006817466cbSJens Wiklander             X->p[i - 1] = X->p[i - v0 - 1];
1007817466cbSJens Wiklander 
1008817466cbSJens Wiklander         for( ; i > 0; i-- )
1009817466cbSJens Wiklander             X->p[i - 1] = 0;
1010817466cbSJens Wiklander     }
1011817466cbSJens Wiklander 
1012817466cbSJens Wiklander     /*
1013817466cbSJens Wiklander      * shift by count % limb_size
1014817466cbSJens Wiklander      */
1015817466cbSJens Wiklander     if( t1 > 0 )
1016817466cbSJens Wiklander     {
1017817466cbSJens Wiklander         for( i = v0; i < X->n; i++ )
1018817466cbSJens Wiklander         {
1019817466cbSJens Wiklander             r1 = X->p[i] >> (biL - t1);
1020817466cbSJens Wiklander             X->p[i] <<= t1;
1021817466cbSJens Wiklander             X->p[i] |= r0;
1022817466cbSJens Wiklander             r0 = r1;
1023817466cbSJens Wiklander         }
1024817466cbSJens Wiklander     }
1025817466cbSJens Wiklander 
1026817466cbSJens Wiklander cleanup:
1027817466cbSJens Wiklander 
1028817466cbSJens Wiklander     return( ret );
1029817466cbSJens Wiklander }
1030817466cbSJens Wiklander 
1031817466cbSJens Wiklander /*
1032817466cbSJens Wiklander  * Right-shift: X >>= count
1033817466cbSJens Wiklander  */
1034817466cbSJens Wiklander int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count )
1035817466cbSJens Wiklander {
1036817466cbSJens Wiklander     size_t i, v0, v1;
1037817466cbSJens Wiklander     mbedtls_mpi_uint r0 = 0, r1;
10383d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
1039817466cbSJens Wiklander 
1040817466cbSJens Wiklander     v0 = count /  biL;
1041817466cbSJens Wiklander     v1 = count & (biL - 1);
1042817466cbSJens Wiklander 
1043817466cbSJens Wiklander     if( v0 > X->n || ( v0 == X->n && v1 > 0 ) )
1044817466cbSJens Wiklander         return mbedtls_mpi_lset( X, 0 );
1045817466cbSJens Wiklander 
1046817466cbSJens Wiklander     /*
1047817466cbSJens Wiklander      * shift by count / limb_size
1048817466cbSJens Wiklander      */
1049817466cbSJens Wiklander     if( v0 > 0 )
1050817466cbSJens Wiklander     {
1051817466cbSJens Wiklander         for( i = 0; i < X->n - v0; i++ )
1052817466cbSJens Wiklander             X->p[i] = X->p[i + v0];
1053817466cbSJens Wiklander 
1054817466cbSJens Wiklander         for( ; i < X->n; i++ )
1055817466cbSJens Wiklander             X->p[i] = 0;
1056817466cbSJens Wiklander     }
1057817466cbSJens Wiklander 
1058817466cbSJens Wiklander     /*
1059817466cbSJens Wiklander      * shift by count % limb_size
1060817466cbSJens Wiklander      */
1061817466cbSJens Wiklander     if( v1 > 0 )
1062817466cbSJens Wiklander     {
1063817466cbSJens Wiklander         for( i = X->n; i > 0; i-- )
1064817466cbSJens Wiklander         {
1065817466cbSJens Wiklander             r1 = X->p[i - 1] << (biL - v1);
1066817466cbSJens Wiklander             X->p[i - 1] >>= v1;
1067817466cbSJens Wiklander             X->p[i - 1] |= r0;
1068817466cbSJens Wiklander             r0 = r1;
1069817466cbSJens Wiklander         }
1070817466cbSJens Wiklander     }
1071817466cbSJens Wiklander 
1072817466cbSJens Wiklander     return( 0 );
1073817466cbSJens Wiklander }
1074817466cbSJens Wiklander 
1075817466cbSJens Wiklander /*
1076817466cbSJens Wiklander  * Compare unsigned values
1077817466cbSJens Wiklander  */
1078817466cbSJens Wiklander int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y )
1079817466cbSJens Wiklander {
1080817466cbSJens Wiklander     size_t i, j;
10813d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
10823d3b0591SJens Wiklander     MPI_VALIDATE_RET( Y != NULL );
1083817466cbSJens Wiklander 
1084817466cbSJens Wiklander     for( i = X->n; i > 0; i-- )
1085817466cbSJens Wiklander         if( X->p[i - 1] != 0 )
1086817466cbSJens Wiklander             break;
1087817466cbSJens Wiklander 
1088817466cbSJens Wiklander     for( j = Y->n; j > 0; j-- )
1089817466cbSJens Wiklander         if( Y->p[j - 1] != 0 )
1090817466cbSJens Wiklander             break;
1091817466cbSJens Wiklander 
1092817466cbSJens Wiklander     if( i == 0 && j == 0 )
1093817466cbSJens Wiklander         return( 0 );
1094817466cbSJens Wiklander 
1095817466cbSJens Wiklander     if( i > j ) return(  1 );
1096817466cbSJens Wiklander     if( j > i ) return( -1 );
1097817466cbSJens Wiklander 
1098817466cbSJens Wiklander     for( ; i > 0; i-- )
1099817466cbSJens Wiklander     {
1100817466cbSJens Wiklander         if( X->p[i - 1] > Y->p[i - 1] ) return(  1 );
1101817466cbSJens Wiklander         if( X->p[i - 1] < Y->p[i - 1] ) return( -1 );
1102817466cbSJens Wiklander     }
1103817466cbSJens Wiklander 
1104817466cbSJens Wiklander     return( 0 );
1105817466cbSJens Wiklander }
1106817466cbSJens Wiklander 
1107817466cbSJens Wiklander /*
1108817466cbSJens Wiklander  * Compare signed values
1109817466cbSJens Wiklander  */
1110817466cbSJens Wiklander int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
1111817466cbSJens Wiklander {
1112817466cbSJens Wiklander     size_t i, j;
11133d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
11143d3b0591SJens Wiklander     MPI_VALIDATE_RET( Y != NULL );
1115817466cbSJens Wiklander 
1116817466cbSJens Wiklander     for( i = X->n; i > 0; i-- )
1117817466cbSJens Wiklander         if( X->p[i - 1] != 0 )
1118817466cbSJens Wiklander             break;
1119817466cbSJens Wiklander 
1120817466cbSJens Wiklander     for( j = Y->n; j > 0; j-- )
1121817466cbSJens Wiklander         if( Y->p[j - 1] != 0 )
1122817466cbSJens Wiklander             break;
1123817466cbSJens Wiklander 
1124817466cbSJens Wiklander     if( i == 0 && j == 0 )
1125817466cbSJens Wiklander         return( 0 );
1126817466cbSJens Wiklander 
1127817466cbSJens Wiklander     if( i > j ) return(  X->s );
1128817466cbSJens Wiklander     if( j > i ) return( -Y->s );
1129817466cbSJens Wiklander 
1130817466cbSJens Wiklander     if( X->s > 0 && Y->s < 0 ) return(  1 );
1131817466cbSJens Wiklander     if( Y->s > 0 && X->s < 0 ) return( -1 );
1132817466cbSJens Wiklander 
1133817466cbSJens Wiklander     for( ; i > 0; i-- )
1134817466cbSJens Wiklander     {
1135817466cbSJens Wiklander         if( X->p[i - 1] > Y->p[i - 1] ) return(  X->s );
1136817466cbSJens Wiklander         if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );
1137817466cbSJens Wiklander     }
1138817466cbSJens Wiklander 
1139817466cbSJens Wiklander     return( 0 );
1140817466cbSJens Wiklander }
1141817466cbSJens Wiklander 
1142817466cbSJens Wiklander /*
1143817466cbSJens Wiklander  * Compare signed values
1144817466cbSJens Wiklander  */
1145817466cbSJens Wiklander int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
1146817466cbSJens Wiklander {
1147817466cbSJens Wiklander     mbedtls_mpi Y;
1148817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
11493d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
1150817466cbSJens Wiklander 
1151817466cbSJens Wiklander     *p  = ( z < 0 ) ? -z : z;
1152817466cbSJens Wiklander     Y.s = ( z < 0 ) ? -1 : 1;
1153817466cbSJens Wiklander     Y.n = 1;
1154817466cbSJens Wiklander     Y.p = p;
1155817466cbSJens Wiklander 
1156817466cbSJens Wiklander     return( mbedtls_mpi_cmp_mpi( X, &Y ) );
1157817466cbSJens Wiklander }
1158817466cbSJens Wiklander 
1159817466cbSJens Wiklander /*
1160817466cbSJens Wiklander  * Unsigned addition: X = |A| + |B|  (HAC 14.7)
1161817466cbSJens Wiklander  */
1162817466cbSJens Wiklander int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1163817466cbSJens Wiklander {
116411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1165817466cbSJens Wiklander     size_t i, j;
1166817466cbSJens Wiklander     mbedtls_mpi_uint *o, *p, c, tmp;
11673d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
11683d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
11693d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1170817466cbSJens Wiklander 
1171817466cbSJens Wiklander     if( X == B )
1172817466cbSJens Wiklander     {
1173817466cbSJens Wiklander         const mbedtls_mpi *T = A; A = X; B = T;
1174817466cbSJens Wiklander     }
1175817466cbSJens Wiklander 
1176817466cbSJens Wiklander     if( X != A )
1177817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
1178817466cbSJens Wiklander 
1179817466cbSJens Wiklander     /*
1180817466cbSJens Wiklander      * X should always be positive as a result of unsigned additions.
1181817466cbSJens Wiklander      */
1182817466cbSJens Wiklander     X->s = 1;
1183817466cbSJens Wiklander 
1184817466cbSJens Wiklander     for( j = B->n; j > 0; j-- )
1185817466cbSJens Wiklander         if( B->p[j - 1] != 0 )
1186817466cbSJens Wiklander             break;
1187817466cbSJens Wiklander 
1188817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
1189817466cbSJens Wiklander 
1190817466cbSJens Wiklander     o = B->p; p = X->p; c = 0;
1191817466cbSJens Wiklander 
1192817466cbSJens Wiklander     /*
1193817466cbSJens Wiklander      * tmp is used because it might happen that p == o
1194817466cbSJens Wiklander      */
1195817466cbSJens Wiklander     for( i = 0; i < j; i++, o++, p++ )
1196817466cbSJens Wiklander     {
1197817466cbSJens Wiklander         tmp= *o;
1198817466cbSJens Wiklander         *p +=  c; c  = ( *p <  c );
1199817466cbSJens Wiklander         *p += tmp; c += ( *p < tmp );
1200817466cbSJens Wiklander     }
1201817466cbSJens Wiklander 
1202817466cbSJens Wiklander     while( c != 0 )
1203817466cbSJens Wiklander     {
1204817466cbSJens Wiklander         if( i >= X->n )
1205817466cbSJens Wiklander         {
1206817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) );
1207817466cbSJens Wiklander             p = X->p + i;
1208817466cbSJens Wiklander         }
1209817466cbSJens Wiklander 
1210817466cbSJens Wiklander         *p += c; c = ( *p < c ); i++; p++;
1211817466cbSJens Wiklander     }
1212817466cbSJens Wiklander 
1213817466cbSJens Wiklander cleanup:
1214817466cbSJens Wiklander 
1215817466cbSJens Wiklander     return( ret );
1216817466cbSJens Wiklander }
1217817466cbSJens Wiklander 
12187901324dSJerome Forissier /**
12197901324dSJerome Forissier  * Helper for mbedtls_mpi subtraction.
12207901324dSJerome Forissier  *
12217901324dSJerome Forissier  * Calculate l - r where l and r have the same size.
12227901324dSJerome Forissier  * This function operates modulo (2^ciL)^n and returns the carry
12237901324dSJerome Forissier  * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise).
12247901324dSJerome Forissier  *
12257901324dSJerome Forissier  * d may be aliased to l or r.
12267901324dSJerome Forissier  *
12277901324dSJerome Forissier  * \param n             Number of limbs of \p d, \p l and \p r.
12287901324dSJerome Forissier  * \param[out] d        The result of the subtraction.
12297901324dSJerome Forissier  * \param[in] l         The left operand.
12307901324dSJerome Forissier  * \param[in] r         The right operand.
12317901324dSJerome Forissier  *
12327901324dSJerome Forissier  * \return              1 if `l < r`.
12337901324dSJerome Forissier  *                      0 if `l >= r`.
1234817466cbSJens Wiklander  */
12357901324dSJerome Forissier static mbedtls_mpi_uint mpi_sub_hlp( size_t n,
12367901324dSJerome Forissier                                      mbedtls_mpi_uint *d,
12377901324dSJerome Forissier                                      const mbedtls_mpi_uint *l,
12387901324dSJerome Forissier                                      const mbedtls_mpi_uint *r )
1239817466cbSJens Wiklander {
1240817466cbSJens Wiklander     size_t i;
12417901324dSJerome Forissier     mbedtls_mpi_uint c = 0, t, z;
1242817466cbSJens Wiklander 
12437901324dSJerome Forissier     for( i = 0; i < n; i++ )
1244817466cbSJens Wiklander     {
12457901324dSJerome Forissier         z = ( l[i] <  c );    t = l[i] - c;
12467901324dSJerome Forissier         c = ( t < r[i] ) + z; d[i] = t - r[i];
1247817466cbSJens Wiklander     }
1248817466cbSJens Wiklander 
12497901324dSJerome Forissier     return( c );
1250817466cbSJens Wiklander }
1251817466cbSJens Wiklander 
1252817466cbSJens Wiklander /*
12537901324dSJerome Forissier  * Unsigned subtraction: X = |A| - |B|  (HAC 14.9, 14.10)
1254817466cbSJens Wiklander  */
1255817466cbSJens Wiklander int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1256817466cbSJens Wiklander {
125711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1258817466cbSJens Wiklander     size_t n;
12597901324dSJerome Forissier     mbedtls_mpi_uint carry;
12603d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
12613d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
12623d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1263817466cbSJens Wiklander 
1264817466cbSJens Wiklander     for( n = B->n; n > 0; n-- )
1265817466cbSJens Wiklander         if( B->p[n - 1] != 0 )
1266817466cbSJens Wiklander             break;
12677901324dSJerome Forissier     if( n > A->n )
12687901324dSJerome Forissier     {
12697901324dSJerome Forissier         /* B >= (2^ciL)^n > A */
12707901324dSJerome Forissier         ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
12717901324dSJerome Forissier         goto cleanup;
12727901324dSJerome Forissier     }
1273817466cbSJens Wiklander 
12747901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) );
12757901324dSJerome Forissier 
12767901324dSJerome Forissier     /* Set the high limbs of X to match A. Don't touch the lower limbs
12777901324dSJerome Forissier      * because X might be aliased to B, and we must not overwrite the
12787901324dSJerome Forissier      * significant digits of B. */
12797901324dSJerome Forissier     if( A->n > n )
12807901324dSJerome Forissier         memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL );
12817901324dSJerome Forissier     if( X->n > A->n )
12827901324dSJerome Forissier         memset( X->p + A->n, 0, ( X->n - A->n ) * ciL );
12837901324dSJerome Forissier 
12847901324dSJerome Forissier     carry = mpi_sub_hlp( n, X->p, A->p, B->p );
12857901324dSJerome Forissier     if( carry != 0 )
12867901324dSJerome Forissier     {
12877901324dSJerome Forissier         /* Propagate the carry to the first nonzero limb of X. */
12887901324dSJerome Forissier         for( ; n < X->n && X->p[n] == 0; n++ )
12897901324dSJerome Forissier             --X->p[n];
12907901324dSJerome Forissier         /* If we ran out of space for the carry, it means that the result
12917901324dSJerome Forissier          * is negative. */
12927901324dSJerome Forissier         if( n == X->n )
12937901324dSJerome Forissier         {
12947901324dSJerome Forissier             ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
12957901324dSJerome Forissier             goto cleanup;
12967901324dSJerome Forissier         }
12977901324dSJerome Forissier         --X->p[n];
12987901324dSJerome Forissier     }
12997901324dSJerome Forissier 
13007901324dSJerome Forissier     /* X should always be positive as a result of unsigned subtractions. */
13017901324dSJerome Forissier     X->s = 1;
1302817466cbSJens Wiklander 
1303817466cbSJens Wiklander cleanup:
1304817466cbSJens Wiklander     return( ret );
1305817466cbSJens Wiklander }
1306817466cbSJens Wiklander 
1307817466cbSJens Wiklander /*
1308817466cbSJens Wiklander  * Signed addition: X = A + B
1309817466cbSJens Wiklander  */
1310817466cbSJens Wiklander int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1311817466cbSJens Wiklander {
13123d3b0591SJens Wiklander     int ret, s;
13133d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
13143d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
13153d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1316817466cbSJens Wiklander 
13173d3b0591SJens Wiklander     s = A->s;
1318817466cbSJens Wiklander     if( A->s * B->s < 0 )
1319817466cbSJens Wiklander     {
1320817466cbSJens Wiklander         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1321817466cbSJens Wiklander         {
1322817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1323817466cbSJens Wiklander             X->s =  s;
1324817466cbSJens Wiklander         }
1325817466cbSJens Wiklander         else
1326817466cbSJens Wiklander         {
1327817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1328817466cbSJens Wiklander             X->s = -s;
1329817466cbSJens Wiklander         }
1330817466cbSJens Wiklander     }
1331817466cbSJens Wiklander     else
1332817466cbSJens Wiklander     {
1333817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1334817466cbSJens Wiklander         X->s = s;
1335817466cbSJens Wiklander     }
1336817466cbSJens Wiklander 
1337817466cbSJens Wiklander cleanup:
1338817466cbSJens Wiklander 
1339817466cbSJens Wiklander     return( ret );
1340817466cbSJens Wiklander }
1341817466cbSJens Wiklander 
1342817466cbSJens Wiklander /*
1343817466cbSJens Wiklander  * Signed subtraction: X = A - B
1344817466cbSJens Wiklander  */
1345817466cbSJens Wiklander int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1346817466cbSJens Wiklander {
13473d3b0591SJens Wiklander     int ret, s;
13483d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
13493d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
13503d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1351817466cbSJens Wiklander 
13523d3b0591SJens Wiklander     s = A->s;
1353817466cbSJens Wiklander     if( A->s * B->s > 0 )
1354817466cbSJens Wiklander     {
1355817466cbSJens Wiklander         if( mbedtls_mpi_cmp_abs( A, B ) >= 0 )
1356817466cbSJens Wiklander         {
1357817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) );
1358817466cbSJens Wiklander             X->s =  s;
1359817466cbSJens Wiklander         }
1360817466cbSJens Wiklander         else
1361817466cbSJens Wiklander         {
1362817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) );
1363817466cbSJens Wiklander             X->s = -s;
1364817466cbSJens Wiklander         }
1365817466cbSJens Wiklander     }
1366817466cbSJens Wiklander     else
1367817466cbSJens Wiklander     {
1368817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) );
1369817466cbSJens Wiklander         X->s = s;
1370817466cbSJens Wiklander     }
1371817466cbSJens Wiklander 
1372817466cbSJens Wiklander cleanup:
1373817466cbSJens Wiklander 
1374817466cbSJens Wiklander     return( ret );
1375817466cbSJens Wiklander }
1376817466cbSJens Wiklander 
1377817466cbSJens Wiklander /*
1378817466cbSJens Wiklander  * Signed addition: X = A + b
1379817466cbSJens Wiklander  */
1380817466cbSJens Wiklander int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1381817466cbSJens Wiklander {
1382*039e02dfSJerome Forissier     mbedtls_mpi B;
1383817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
13843d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
13853d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
1386817466cbSJens Wiklander 
1387817466cbSJens Wiklander     p[0] = ( b < 0 ) ? -b : b;
1388*039e02dfSJerome Forissier     B.s = ( b < 0 ) ? -1 : 1;
1389*039e02dfSJerome Forissier     B.n = 1;
1390*039e02dfSJerome Forissier     B.p = p;
1391817466cbSJens Wiklander 
1392*039e02dfSJerome Forissier     return( mbedtls_mpi_add_mpi( X, A, &B ) );
1393817466cbSJens Wiklander }
1394817466cbSJens Wiklander 
1395817466cbSJens Wiklander /*
1396817466cbSJens Wiklander  * Signed subtraction: X = A - b
1397817466cbSJens Wiklander  */
1398817466cbSJens Wiklander int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1399817466cbSJens Wiklander {
1400*039e02dfSJerome Forissier     mbedtls_mpi B;
1401817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
14023d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
14033d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
1404817466cbSJens Wiklander 
1405817466cbSJens Wiklander     p[0] = ( b < 0 ) ? -b : b;
1406*039e02dfSJerome Forissier     B.s = ( b < 0 ) ? -1 : 1;
1407*039e02dfSJerome Forissier     B.n = 1;
1408*039e02dfSJerome Forissier     B.p = p;
1409817466cbSJens Wiklander 
1410*039e02dfSJerome Forissier     return( mbedtls_mpi_sub_mpi( X, A, &B ) );
1411817466cbSJens Wiklander }
1412817466cbSJens Wiklander 
14137901324dSJerome Forissier /** Helper for mbedtls_mpi multiplication.
14147901324dSJerome Forissier  *
14157901324dSJerome Forissier  * Add \p b * \p s to \p d.
14167901324dSJerome Forissier  *
14177901324dSJerome Forissier  * \param i             The number of limbs of \p s.
14187901324dSJerome Forissier  * \param[in] s         A bignum to multiply, of size \p i.
14197901324dSJerome Forissier  *                      It may overlap with \p d, but only if
14207901324dSJerome Forissier  *                      \p d <= \p s.
14217901324dSJerome Forissier  *                      Its leading limb must not be \c 0.
14227901324dSJerome Forissier  * \param[in,out] d     The bignum to add to.
14237901324dSJerome Forissier  *                      It must be sufficiently large to store the
14247901324dSJerome Forissier  *                      result of the multiplication. This means
14257901324dSJerome Forissier  *                      \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b
14267901324dSJerome Forissier  *                      is not known a priori.
14277901324dSJerome Forissier  * \param b             A scalar to multiply.
1428817466cbSJens Wiklander  */
1429817466cbSJens Wiklander static
1430817466cbSJens Wiklander #if defined(__APPLE__) && defined(__arm__)
1431817466cbSJens Wiklander /*
1432817466cbSJens Wiklander  * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)
1433817466cbSJens Wiklander  * appears to need this to prevent bad ARM code generation at -O3.
1434817466cbSJens Wiklander  */
1435817466cbSJens Wiklander __attribute__ ((noinline))
1436817466cbSJens Wiklander #endif
14377901324dSJerome Forissier void mpi_mul_hlp( size_t i,
14387901324dSJerome Forissier                   const mbedtls_mpi_uint *s,
14397901324dSJerome Forissier                   mbedtls_mpi_uint *d,
14407901324dSJerome Forissier                   mbedtls_mpi_uint b )
1441817466cbSJens Wiklander {
1442817466cbSJens Wiklander     mbedtls_mpi_uint c = 0, t = 0;
1443817466cbSJens Wiklander 
1444817466cbSJens Wiklander #if defined(MULADDC_HUIT)
1445817466cbSJens Wiklander     for( ; i >= 8; i -= 8 )
1446817466cbSJens Wiklander     {
1447817466cbSJens Wiklander         MULADDC_INIT
1448817466cbSJens Wiklander         MULADDC_HUIT
1449817466cbSJens Wiklander         MULADDC_STOP
1450817466cbSJens Wiklander     }
1451817466cbSJens Wiklander 
1452817466cbSJens Wiklander     for( ; i > 0; i-- )
1453817466cbSJens Wiklander     {
1454817466cbSJens Wiklander         MULADDC_INIT
1455817466cbSJens Wiklander         MULADDC_CORE
1456817466cbSJens Wiklander         MULADDC_STOP
1457817466cbSJens Wiklander     }
1458817466cbSJens Wiklander #else /* MULADDC_HUIT */
1459817466cbSJens Wiklander     for( ; i >= 16; i -= 16 )
1460817466cbSJens Wiklander     {
1461817466cbSJens Wiklander         MULADDC_INIT
1462817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1463817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1464817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1465817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1466817466cbSJens Wiklander 
1467817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1468817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1469817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1470817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1471817466cbSJens Wiklander         MULADDC_STOP
1472817466cbSJens Wiklander     }
1473817466cbSJens Wiklander 
1474817466cbSJens Wiklander     for( ; i >= 8; i -= 8 )
1475817466cbSJens Wiklander     {
1476817466cbSJens Wiklander         MULADDC_INIT
1477817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1478817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1479817466cbSJens Wiklander 
1480817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1481817466cbSJens Wiklander         MULADDC_CORE   MULADDC_CORE
1482817466cbSJens Wiklander         MULADDC_STOP
1483817466cbSJens Wiklander     }
1484817466cbSJens Wiklander 
1485817466cbSJens Wiklander     for( ; i > 0; i-- )
1486817466cbSJens Wiklander     {
1487817466cbSJens Wiklander         MULADDC_INIT
1488817466cbSJens Wiklander         MULADDC_CORE
1489817466cbSJens Wiklander         MULADDC_STOP
1490817466cbSJens Wiklander     }
1491817466cbSJens Wiklander #endif /* MULADDC_HUIT */
1492817466cbSJens Wiklander 
1493817466cbSJens Wiklander     t++;
1494817466cbSJens Wiklander 
14957901324dSJerome Forissier     while( c != 0 )
14967901324dSJerome Forissier     {
1497817466cbSJens Wiklander         *d += c; c = ( *d < c ); d++;
1498817466cbSJens Wiklander     }
1499817466cbSJens Wiklander }
1500817466cbSJens Wiklander 
1501817466cbSJens Wiklander /*
1502817466cbSJens Wiklander  * Baseline multiplication: X = A * B  (HAC 14.12)
1503817466cbSJens Wiklander  */
1504817466cbSJens Wiklander int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
1505817466cbSJens Wiklander {
150611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1507817466cbSJens Wiklander     size_t i, j;
1508817466cbSJens Wiklander     mbedtls_mpi TA, TB;
15097901324dSJerome Forissier     int result_is_zero = 0;
15103d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
15113d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
15123d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1513817466cbSJens Wiklander 
151498bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB );
1515817466cbSJens Wiklander 
1516817466cbSJens Wiklander     if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; }
1517817466cbSJens Wiklander     if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; }
1518817466cbSJens Wiklander 
1519817466cbSJens Wiklander     for( i = A->n; i > 0; i-- )
1520817466cbSJens Wiklander         if( A->p[i - 1] != 0 )
1521817466cbSJens Wiklander             break;
15227901324dSJerome Forissier     if( i == 0 )
15237901324dSJerome Forissier         result_is_zero = 1;
1524817466cbSJens Wiklander 
1525817466cbSJens Wiklander     for( j = B->n; j > 0; j-- )
1526817466cbSJens Wiklander         if( B->p[j - 1] != 0 )
1527817466cbSJens Wiklander             break;
15287901324dSJerome Forissier     if( j == 0 )
15297901324dSJerome Forissier         result_is_zero = 1;
1530817466cbSJens Wiklander 
1531817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) );
1532817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );
1533817466cbSJens Wiklander 
15343d3b0591SJens Wiklander     for( ; j > 0; j-- )
15353d3b0591SJens Wiklander         mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] );
1536817466cbSJens Wiklander 
15377901324dSJerome Forissier     /* If the result is 0, we don't shortcut the operation, which reduces
15387901324dSJerome Forissier      * but does not eliminate side channels leaking the zero-ness. We do
15397901324dSJerome Forissier      * need to take care to set the sign bit properly since the library does
15407901324dSJerome Forissier      * not fully support an MPI object with a value of 0 and s == -1. */
15417901324dSJerome Forissier     if( result_is_zero )
15427901324dSJerome Forissier         X->s = 1;
15437901324dSJerome Forissier     else
1544817466cbSJens Wiklander         X->s = A->s * B->s;
1545817466cbSJens Wiklander 
1546817466cbSJens Wiklander cleanup:
1547817466cbSJens Wiklander 
1548817466cbSJens Wiklander     mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA );
1549817466cbSJens Wiklander 
1550817466cbSJens Wiklander     return( ret );
1551817466cbSJens Wiklander }
1552817466cbSJens Wiklander 
1553817466cbSJens Wiklander /*
1554817466cbSJens Wiklander  * Baseline multiplication: X = A * b
1555817466cbSJens Wiklander  */
1556817466cbSJens Wiklander int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b )
1557817466cbSJens Wiklander {
15583d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
15593d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
1560817466cbSJens Wiklander 
15617901324dSJerome Forissier     /* mpi_mul_hlp can't deal with a leading 0. */
15627901324dSJerome Forissier     size_t n = A->n;
15637901324dSJerome Forissier     while( n > 0 && A->p[n - 1] == 0 )
15647901324dSJerome Forissier         --n;
1565817466cbSJens Wiklander 
15667901324dSJerome Forissier     /* The general method below doesn't work if n==0 or b==0. By chance
15677901324dSJerome Forissier      * calculating the result is trivial in those cases. */
15687901324dSJerome Forissier     if( b == 0 || n == 0 )
15697901324dSJerome Forissier     {
15707901324dSJerome Forissier         return( mbedtls_mpi_lset( X, 0 ) );
15717901324dSJerome Forissier     }
15727901324dSJerome Forissier 
15737901324dSJerome Forissier     /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */
15747901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
15757901324dSJerome Forissier     /* In general, A * b requires 1 limb more than b. If
15767901324dSJerome Forissier      * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same
15777901324dSJerome Forissier      * number of limbs as A and the call to grow() is not required since
15787901324dSJerome Forissier      * copy() will take care of the growth if needed. However, experimentally,
15797901324dSJerome Forissier      * making the call to grow() unconditional causes slightly fewer
15807901324dSJerome Forissier      * calls to calloc() in ECP code, presumably because it reuses the
15817901324dSJerome Forissier      * same mpi for a while and this way the mpi is more likely to directly
15827901324dSJerome Forissier      * grow to its final size. */
15837901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) );
15847901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) );
15857901324dSJerome Forissier     mpi_mul_hlp( n, A->p, X->p, b - 1 );
15867901324dSJerome Forissier 
15877901324dSJerome Forissier cleanup:
15887901324dSJerome Forissier     return( ret );
1589817466cbSJens Wiklander }
1590817466cbSJens Wiklander 
1591817466cbSJens Wiklander /*
1592817466cbSJens Wiklander  * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and
1593817466cbSJens Wiklander  * mbedtls_mpi_uint divisor, d
1594817466cbSJens Wiklander  */
1595817466cbSJens Wiklander static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
1596817466cbSJens Wiklander             mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r )
1597817466cbSJens Wiklander {
1598817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL)
1599817466cbSJens Wiklander     mbedtls_t_udbl dividend, quotient;
1600817466cbSJens Wiklander #else
1601817466cbSJens Wiklander     const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH;
1602817466cbSJens Wiklander     const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1;
1603817466cbSJens Wiklander     mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient;
1604817466cbSJens Wiklander     mbedtls_mpi_uint u0_msw, u0_lsw;
1605817466cbSJens Wiklander     size_t s;
1606817466cbSJens Wiklander #endif
1607817466cbSJens Wiklander 
1608817466cbSJens Wiklander     /*
1609817466cbSJens Wiklander      * Check for overflow
1610817466cbSJens Wiklander      */
1611817466cbSJens Wiklander     if( 0 == d || u1 >= d )
1612817466cbSJens Wiklander     {
1613817466cbSJens Wiklander         if (r != NULL) *r = ~0;
1614817466cbSJens Wiklander 
1615817466cbSJens Wiklander         return ( ~0 );
1616817466cbSJens Wiklander     }
1617817466cbSJens Wiklander 
1618817466cbSJens Wiklander #if defined(MBEDTLS_HAVE_UDBL)
1619817466cbSJens Wiklander     dividend  = (mbedtls_t_udbl) u1 << biL;
1620817466cbSJens Wiklander     dividend |= (mbedtls_t_udbl) u0;
1621817466cbSJens Wiklander     quotient = dividend / d;
1622817466cbSJens Wiklander     if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 )
1623817466cbSJens Wiklander         quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1;
1624817466cbSJens Wiklander 
1625817466cbSJens Wiklander     if( r != NULL )
1626817466cbSJens Wiklander         *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) );
1627817466cbSJens Wiklander 
1628817466cbSJens Wiklander     return (mbedtls_mpi_uint) quotient;
1629817466cbSJens Wiklander #else
1630817466cbSJens Wiklander 
1631817466cbSJens Wiklander     /*
1632817466cbSJens Wiklander      * Algorithm D, Section 4.3.1 - The Art of Computer Programming
1633817466cbSJens Wiklander      *   Vol. 2 - Seminumerical Algorithms, Knuth
1634817466cbSJens Wiklander      */
1635817466cbSJens Wiklander 
1636817466cbSJens Wiklander     /*
1637817466cbSJens Wiklander      * Normalize the divisor, d, and dividend, u0, u1
1638817466cbSJens Wiklander      */
1639817466cbSJens Wiklander     s = mbedtls_clz( d );
1640817466cbSJens Wiklander     d = d << s;
1641817466cbSJens Wiklander 
1642817466cbSJens Wiklander     u1 = u1 << s;
1643817466cbSJens Wiklander     u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) );
1644817466cbSJens Wiklander     u0 =  u0 << s;
1645817466cbSJens Wiklander 
1646817466cbSJens Wiklander     d1 = d >> biH;
1647817466cbSJens Wiklander     d0 = d & uint_halfword_mask;
1648817466cbSJens Wiklander 
1649817466cbSJens Wiklander     u0_msw = u0 >> biH;
1650817466cbSJens Wiklander     u0_lsw = u0 & uint_halfword_mask;
1651817466cbSJens Wiklander 
1652817466cbSJens Wiklander     /*
1653817466cbSJens Wiklander      * Find the first quotient and remainder
1654817466cbSJens Wiklander      */
1655817466cbSJens Wiklander     q1 = u1 / d1;
1656817466cbSJens Wiklander     r0 = u1 - d1 * q1;
1657817466cbSJens Wiklander 
1658817466cbSJens Wiklander     while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) )
1659817466cbSJens Wiklander     {
1660817466cbSJens Wiklander         q1 -= 1;
1661817466cbSJens Wiklander         r0 += d1;
1662817466cbSJens Wiklander 
1663817466cbSJens Wiklander         if ( r0 >= radix ) break;
1664817466cbSJens Wiklander     }
1665817466cbSJens Wiklander 
1666817466cbSJens Wiklander     rAX = ( u1 * radix ) + ( u0_msw - q1 * d );
1667817466cbSJens Wiklander     q0 = rAX / d1;
1668817466cbSJens Wiklander     r0 = rAX - q0 * d1;
1669817466cbSJens Wiklander 
1670817466cbSJens Wiklander     while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) )
1671817466cbSJens Wiklander     {
1672817466cbSJens Wiklander         q0 -= 1;
1673817466cbSJens Wiklander         r0 += d1;
1674817466cbSJens Wiklander 
1675817466cbSJens Wiklander         if ( r0 >= radix ) break;
1676817466cbSJens Wiklander     }
1677817466cbSJens Wiklander 
1678817466cbSJens Wiklander     if (r != NULL)
1679817466cbSJens Wiklander         *r = ( rAX * radix + u0_lsw - q0 * d ) >> s;
1680817466cbSJens Wiklander 
1681817466cbSJens Wiklander     quotient = q1 * radix + q0;
1682817466cbSJens Wiklander 
1683817466cbSJens Wiklander     return quotient;
1684817466cbSJens Wiklander #endif
1685817466cbSJens Wiklander }
1686817466cbSJens Wiklander 
1687817466cbSJens Wiklander /*
1688817466cbSJens Wiklander  * Division by mbedtls_mpi: A = Q * B + R  (HAC 14.20)
1689817466cbSJens Wiklander  */
16903d3b0591SJens Wiklander int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
16913d3b0591SJens Wiklander                          const mbedtls_mpi *B )
1692817466cbSJens Wiklander {
169311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1694817466cbSJens Wiklander     size_t i, n, t, k;
1695817466cbSJens Wiklander     mbedtls_mpi X, Y, Z, T1, T2;
169611fa71b9SJerome Forissier     mbedtls_mpi_uint TP2[3];
16973d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
16983d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1699817466cbSJens Wiklander 
1700817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( B, 0 ) == 0 )
1701817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1702817466cbSJens Wiklander 
170398bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &X ); mbedtls_mpi_init_mempool( &Y );
170498bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &Z ); mbedtls_mpi_init_mempool( &T1 );
170511fa71b9SJerome Forissier     /*
170611fa71b9SJerome Forissier      * Avoid dynamic memory allocations for constant-size T2.
170711fa71b9SJerome Forissier      *
170811fa71b9SJerome Forissier      * T2 is used for comparison only and the 3 limbs are assigned explicitly,
170911fa71b9SJerome Forissier      * so nobody increase the size of the MPI and we're safe to use an on-stack
171011fa71b9SJerome Forissier      * buffer.
171111fa71b9SJerome Forissier      */
171211fa71b9SJerome Forissier     T2.s = 1;
171311fa71b9SJerome Forissier     T2.n = sizeof( TP2 ) / sizeof( *TP2 );
171411fa71b9SJerome Forissier     T2.p = TP2;
1715817466cbSJens Wiklander 
1716817466cbSJens Wiklander     if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
1717817466cbSJens Wiklander     {
1718817466cbSJens Wiklander         if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) );
1719817466cbSJens Wiklander         if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) );
1720817466cbSJens Wiklander         return( 0 );
1721817466cbSJens Wiklander     }
1722817466cbSJens Wiklander 
1723817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) );
1724817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) );
1725817466cbSJens Wiklander     X.s = Y.s = 1;
1726817466cbSJens Wiklander 
1727817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
1728817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z,  0 ) );
17297901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) );
1730817466cbSJens Wiklander 
1731817466cbSJens Wiklander     k = mbedtls_mpi_bitlen( &Y ) % biL;
1732817466cbSJens Wiklander     if( k < biL - 1 )
1733817466cbSJens Wiklander     {
1734817466cbSJens Wiklander         k = biL - 1 - k;
1735817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) );
1736817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) );
1737817466cbSJens Wiklander     }
1738817466cbSJens Wiklander     else k = 0;
1739817466cbSJens Wiklander 
1740817466cbSJens Wiklander     n = X.n - 1;
1741817466cbSJens Wiklander     t = Y.n - 1;
1742817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) );
1743817466cbSJens Wiklander 
1744817466cbSJens Wiklander     while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 )
1745817466cbSJens Wiklander     {
1746817466cbSJens Wiklander         Z.p[n - t]++;
1747817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) );
1748817466cbSJens Wiklander     }
1749817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) );
1750817466cbSJens Wiklander 
1751817466cbSJens Wiklander     for( i = n; i > t ; i-- )
1752817466cbSJens Wiklander     {
1753817466cbSJens Wiklander         if( X.p[i] >= Y.p[t] )
1754817466cbSJens Wiklander             Z.p[i - t - 1] = ~0;
1755817466cbSJens Wiklander         else
1756817466cbSJens Wiklander         {
1757817466cbSJens Wiklander             Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
1758817466cbSJens Wiklander                                                             Y.p[t], NULL);
1759817466cbSJens Wiklander         }
1760817466cbSJens Wiklander 
176111fa71b9SJerome Forissier         T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
176211fa71b9SJerome Forissier         T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
176311fa71b9SJerome Forissier         T2.p[2] = X.p[i];
176411fa71b9SJerome Forissier 
1765817466cbSJens Wiklander         Z.p[i - t - 1]++;
1766817466cbSJens Wiklander         do
1767817466cbSJens Wiklander         {
1768817466cbSJens Wiklander             Z.p[i - t - 1]--;
1769817466cbSJens Wiklander 
1770817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) );
1771817466cbSJens Wiklander             T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
1772817466cbSJens Wiklander             T1.p[1] = Y.p[t];
1773817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1774817466cbSJens Wiklander         }
1775817466cbSJens Wiklander         while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
1776817466cbSJens Wiklander 
1777817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1778817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1,  biL * ( i - t - 1 ) ) );
1779817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) );
1780817466cbSJens Wiklander 
1781817466cbSJens Wiklander         if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 )
1782817466cbSJens Wiklander         {
1783817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) );
1784817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) );
1785817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) );
1786817466cbSJens Wiklander             Z.p[i - t - 1]--;
1787817466cbSJens Wiklander         }
1788817466cbSJens Wiklander     }
1789817466cbSJens Wiklander 
1790817466cbSJens Wiklander     if( Q != NULL )
1791817466cbSJens Wiklander     {
1792817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) );
1793817466cbSJens Wiklander         Q->s = A->s * B->s;
1794817466cbSJens Wiklander     }
1795817466cbSJens Wiklander 
1796817466cbSJens Wiklander     if( R != NULL )
1797817466cbSJens Wiklander     {
1798817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) );
1799817466cbSJens Wiklander         X.s = A->s;
1800817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) );
1801817466cbSJens Wiklander 
1802817466cbSJens Wiklander         if( mbedtls_mpi_cmp_int( R, 0 ) == 0 )
1803817466cbSJens Wiklander             R->s = 1;
1804817466cbSJens Wiklander     }
1805817466cbSJens Wiklander 
1806817466cbSJens Wiklander cleanup:
1807817466cbSJens Wiklander 
1808817466cbSJens Wiklander     mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
180911fa71b9SJerome Forissier     mbedtls_mpi_free( &T1 );
181011fa71b9SJerome Forissier     mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
1811817466cbSJens Wiklander 
1812817466cbSJens Wiklander     return( ret );
1813817466cbSJens Wiklander }
1814817466cbSJens Wiklander 
1815817466cbSJens Wiklander /*
1816817466cbSJens Wiklander  * Division by int: A = Q * b + R
1817817466cbSJens Wiklander  */
18183d3b0591SJens Wiklander int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
18193d3b0591SJens Wiklander                          const mbedtls_mpi *A,
18203d3b0591SJens Wiklander                          mbedtls_mpi_sint b )
1821817466cbSJens Wiklander {
1822*039e02dfSJerome Forissier     mbedtls_mpi B;
1823817466cbSJens Wiklander     mbedtls_mpi_uint p[1];
18243d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
1825817466cbSJens Wiklander 
1826817466cbSJens Wiklander     p[0] = ( b < 0 ) ? -b : b;
1827*039e02dfSJerome Forissier     B.s = ( b < 0 ) ? -1 : 1;
1828*039e02dfSJerome Forissier     B.n = 1;
1829*039e02dfSJerome Forissier     B.p = p;
1830817466cbSJens Wiklander 
1831*039e02dfSJerome Forissier     return( mbedtls_mpi_div_mpi( Q, R, A, &B ) );
1832817466cbSJens Wiklander }
1833817466cbSJens Wiklander 
1834817466cbSJens Wiklander /*
1835817466cbSJens Wiklander  * Modulo: R = A mod B
1836817466cbSJens Wiklander  */
1837817466cbSJens Wiklander int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
1838817466cbSJens Wiklander {
183911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
18403d3b0591SJens Wiklander     MPI_VALIDATE_RET( R != NULL );
18413d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
18423d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
1843817466cbSJens Wiklander 
1844817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( B, 0 ) < 0 )
1845817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1846817466cbSJens Wiklander 
1847817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) );
1848817466cbSJens Wiklander 
1849817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( R, 0 ) < 0 )
1850817466cbSJens Wiklander       MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) );
1851817466cbSJens Wiklander 
1852817466cbSJens Wiklander     while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 )
1853817466cbSJens Wiklander       MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) );
1854817466cbSJens Wiklander 
1855817466cbSJens Wiklander cleanup:
1856817466cbSJens Wiklander 
1857817466cbSJens Wiklander     return( ret );
1858817466cbSJens Wiklander }
1859817466cbSJens Wiklander 
1860817466cbSJens Wiklander /*
1861817466cbSJens Wiklander  * Modulo: r = A mod b
1862817466cbSJens Wiklander  */
1863817466cbSJens Wiklander int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b )
1864817466cbSJens Wiklander {
1865817466cbSJens Wiklander     size_t i;
1866817466cbSJens Wiklander     mbedtls_mpi_uint x, y, z;
18673d3b0591SJens Wiklander     MPI_VALIDATE_RET( r != NULL );
18683d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
1869817466cbSJens Wiklander 
1870817466cbSJens Wiklander     if( b == 0 )
1871817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
1872817466cbSJens Wiklander 
1873817466cbSJens Wiklander     if( b < 0 )
1874817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE );
1875817466cbSJens Wiklander 
1876817466cbSJens Wiklander     /*
1877817466cbSJens Wiklander      * handle trivial cases
1878817466cbSJens Wiklander      */
1879*039e02dfSJerome Forissier     if( b == 1 || A->n == 0 )
1880817466cbSJens Wiklander     {
1881817466cbSJens Wiklander         *r = 0;
1882817466cbSJens Wiklander         return( 0 );
1883817466cbSJens Wiklander     }
1884817466cbSJens Wiklander 
1885817466cbSJens Wiklander     if( b == 2 )
1886817466cbSJens Wiklander     {
1887817466cbSJens Wiklander         *r = A->p[0] & 1;
1888817466cbSJens Wiklander         return( 0 );
1889817466cbSJens Wiklander     }
1890817466cbSJens Wiklander 
1891817466cbSJens Wiklander     /*
1892817466cbSJens Wiklander      * general case
1893817466cbSJens Wiklander      */
1894817466cbSJens Wiklander     for( i = A->n, y = 0; i > 0; i-- )
1895817466cbSJens Wiklander     {
1896817466cbSJens Wiklander         x  = A->p[i - 1];
1897817466cbSJens Wiklander         y  = ( y << biH ) | ( x >> biH );
1898817466cbSJens Wiklander         z  = y / b;
1899817466cbSJens Wiklander         y -= z * b;
1900817466cbSJens Wiklander 
1901817466cbSJens Wiklander         x <<= biH;
1902817466cbSJens Wiklander         y  = ( y << biH ) | ( x >> biH );
1903817466cbSJens Wiklander         z  = y / b;
1904817466cbSJens Wiklander         y -= z * b;
1905817466cbSJens Wiklander     }
1906817466cbSJens Wiklander 
1907817466cbSJens Wiklander     /*
1908817466cbSJens Wiklander      * If A is negative, then the current y represents a negative value.
1909817466cbSJens Wiklander      * Flipping it to the positive side.
1910817466cbSJens Wiklander      */
1911817466cbSJens Wiklander     if( A->s < 0 && y != 0 )
1912817466cbSJens Wiklander         y = b - y;
1913817466cbSJens Wiklander 
1914817466cbSJens Wiklander     *r = y;
1915817466cbSJens Wiklander 
1916817466cbSJens Wiklander     return( 0 );
1917817466cbSJens Wiklander }
1918817466cbSJens Wiklander 
1919817466cbSJens Wiklander /*
1920817466cbSJens Wiklander  * Fast Montgomery initialization (thanks to Tom St Denis)
1921817466cbSJens Wiklander  */
19227901324dSJerome Forissier static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
1923817466cbSJens Wiklander {
1924817466cbSJens Wiklander     mbedtls_mpi_uint x, m0 = N->p[0];
1925817466cbSJens Wiklander     unsigned int i;
1926817466cbSJens Wiklander 
1927817466cbSJens Wiklander     x  = m0;
1928817466cbSJens Wiklander     x += ( ( m0 + 2 ) & 4 ) << 1;
1929817466cbSJens Wiklander 
1930817466cbSJens Wiklander     for( i = biL; i >= 8; i /= 2 )
1931817466cbSJens Wiklander         x *= ( 2 - ( m0 * x ) );
1932817466cbSJens Wiklander 
1933817466cbSJens Wiklander     *mm = ~x + 1;
1934817466cbSJens Wiklander }
1935817466cbSJens Wiklander 
19367901324dSJerome Forissier void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
19377901324dSJerome Forissier {
19387901324dSJerome Forissier 	mpi_montg_init( mm, N );
19397901324dSJerome Forissier }
19407901324dSJerome Forissier 
19417901324dSJerome Forissier /** Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
19427901324dSJerome Forissier  *
19437901324dSJerome Forissier  * \param[in,out]   A   One of the numbers to multiply.
19447901324dSJerome Forissier  *                      It must have at least as many limbs as N
19457901324dSJerome Forissier  *                      (A->n >= N->n), and any limbs beyond n are ignored.
19467901324dSJerome Forissier  *                      On successful completion, A contains the result of
19477901324dSJerome Forissier  *                      the multiplication A * B * R^-1 mod N where
19487901324dSJerome Forissier  *                      R = (2^ciL)^n.
19497901324dSJerome Forissier  * \param[in]       B   One of the numbers to multiply.
19507901324dSJerome Forissier  *                      It must be nonzero and must not have more limbs than N
19517901324dSJerome Forissier  *                      (B->n <= N->n).
19527901324dSJerome Forissier  * \param[in]       N   The modulo. N must be odd.
19537901324dSJerome Forissier  * \param           mm  The value calculated by `mpi_montg_init(&mm, N)`.
19547901324dSJerome Forissier  *                      This is -N^-1 mod 2^ciL.
19557901324dSJerome Forissier  * \param[in,out]   T   A bignum for temporary storage.
19567901324dSJerome Forissier  *                      It must be at least twice the limb size of N plus 2
19577901324dSJerome Forissier  *                      (T->n >= 2 * (N->n + 1)).
19587901324dSJerome Forissier  *                      Its initial content is unused and
19597901324dSJerome Forissier  *                      its final content is indeterminate.
19607901324dSJerome Forissier  *                      Note that unlike the usual convention in the library
19617901324dSJerome Forissier  *                      for `const mbedtls_mpi*`, the content of T can change.
1962817466cbSJens Wiklander  */
19637901324dSJerome Forissier static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
1964817466cbSJens Wiklander                          const mbedtls_mpi *T )
1965817466cbSJens Wiklander {
1966817466cbSJens Wiklander     size_t i, n, m;
1967817466cbSJens Wiklander     mbedtls_mpi_uint u0, u1, *d;
1968817466cbSJens Wiklander 
1969817466cbSJens Wiklander     memset( T->p, 0, T->n * ciL );
1970817466cbSJens Wiklander 
1971817466cbSJens Wiklander     d = T->p;
1972817466cbSJens Wiklander     n = N->n;
1973817466cbSJens Wiklander     m = ( B->n < n ) ? B->n : n;
1974817466cbSJens Wiklander 
1975817466cbSJens Wiklander     for( i = 0; i < n; i++ )
1976817466cbSJens Wiklander     {
1977817466cbSJens Wiklander         /*
1978817466cbSJens Wiklander          * T = (T + u0*B + u1*N) / 2^biL
1979817466cbSJens Wiklander          */
1980817466cbSJens Wiklander         u0 = A->p[i];
1981817466cbSJens Wiklander         u1 = ( d[0] + u0 * B->p[0] ) * mm;
1982817466cbSJens Wiklander 
1983817466cbSJens Wiklander         mpi_mul_hlp( m, B->p, d, u0 );
1984817466cbSJens Wiklander         mpi_mul_hlp( n, N->p, d, u1 );
1985817466cbSJens Wiklander 
1986817466cbSJens Wiklander         *d++ = u0; d[n + 1] = 0;
1987817466cbSJens Wiklander     }
1988817466cbSJens Wiklander 
19897901324dSJerome Forissier     /* At this point, d is either the desired result or the desired result
19907901324dSJerome Forissier      * plus N. We now potentially subtract N, avoiding leaking whether the
19917901324dSJerome Forissier      * subtraction is performed through side channels. */
1992817466cbSJens Wiklander 
19937901324dSJerome Forissier     /* Copy the n least significant limbs of d to A, so that
19947901324dSJerome Forissier      * A = d if d < N (recall that N has n limbs). */
19957901324dSJerome Forissier     memcpy( A->p, d, n * ciL );
19967901324dSJerome Forissier     /* If d >= N then we want to set A to d - N. To prevent timing attacks,
19977901324dSJerome Forissier      * do the calculation without using conditional tests. */
19987901324dSJerome Forissier     /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */
19997901324dSJerome Forissier     d[n] += 1;
20007901324dSJerome Forissier     d[n] -= mpi_sub_hlp( n, d, d, N->p );
20017901324dSJerome Forissier     /* If d0 < N then d < (2^biL)^n
20027901324dSJerome Forissier      * so d[n] == 0 and we want to keep A as it is.
20037901324dSJerome Forissier      * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n
20047901324dSJerome Forissier      * so d[n] == 1 and we want to set A to the result of the subtraction
20057901324dSJerome Forissier      * which is d - (2^biL)^n, i.e. the n least significant limbs of d.
20067901324dSJerome Forissier      * This exactly corresponds to a conditional assignment. */
2007*039e02dfSJerome Forissier     mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] );
20087901324dSJerome Forissier }
2009817466cbSJens Wiklander 
20107901324dSJerome Forissier void mbedtls_mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,
20117901324dSJerome Forissier                           const mbedtls_mpi *T )
20127901324dSJerome Forissier {
20137901324dSJerome Forissier     mpi_montmul( A, B, N, mm, T);
2014817466cbSJens Wiklander }
2015817466cbSJens Wiklander 
2016817466cbSJens Wiklander /*
2017817466cbSJens Wiklander  * Montgomery reduction: A = A * R^-1 mod N
20187901324dSJerome Forissier  *
20197901324dSJerome Forissier  * See mpi_montmul() regarding constraints and guarantees on the parameters.
2020817466cbSJens Wiklander  */
20217901324dSJerome Forissier static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
202262f21181SJens Wiklander                          mbedtls_mpi_uint mm, const mbedtls_mpi *T )
2023817466cbSJens Wiklander {
2024817466cbSJens Wiklander     mbedtls_mpi_uint z = 1;
2025817466cbSJens Wiklander     mbedtls_mpi U;
2026817466cbSJens Wiklander 
2027817466cbSJens Wiklander     U.n = U.s = (int) z;
2028817466cbSJens Wiklander     U.p = &z;
2029817466cbSJens Wiklander 
20307901324dSJerome Forissier     mpi_montmul( A, &U, N, mm, T );
20317901324dSJerome Forissier }
20327901324dSJerome Forissier 
20337901324dSJerome Forissier void mbedtls_mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,
20347901324dSJerome Forissier                           mbedtls_mpi_uint mm, const mbedtls_mpi *T )
20357901324dSJerome Forissier {
20367901324dSJerome Forissier     mpi_montred( A, N, mm, T );
20377901324dSJerome Forissier }
20387901324dSJerome Forissier 
20397901324dSJerome Forissier /**
20407901324dSJerome Forissier  * Select an MPI from a table without leaking the index.
20417901324dSJerome Forissier  *
20427901324dSJerome Forissier  * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
20437901324dSJerome Forissier  * reads the entire table in order to avoid leaking the value of idx to an
20447901324dSJerome Forissier  * attacker able to observe memory access patterns.
20457901324dSJerome Forissier  *
20467901324dSJerome Forissier  * \param[out] R        Where to write the selected MPI.
20477901324dSJerome Forissier  * \param[in] T         The table to read from.
20487901324dSJerome Forissier  * \param[in] T_size    The number of elements in the table.
20497901324dSJerome Forissier  * \param[in] idx       The index of the element to select;
20507901324dSJerome Forissier  *                      this must satisfy 0 <= idx < T_size.
20517901324dSJerome Forissier  *
20527901324dSJerome Forissier  * \return \c 0 on success, or a negative error code.
20537901324dSJerome Forissier  */
20547901324dSJerome Forissier static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx )
20557901324dSJerome Forissier {
20567901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
20577901324dSJerome Forissier 
20587901324dSJerome Forissier     for( size_t i = 0; i < T_size; i++ )
20597901324dSJerome Forissier     {
20607901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i],
2061*039e02dfSJerome Forissier                         (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) );
20627901324dSJerome Forissier     }
20637901324dSJerome Forissier 
20647901324dSJerome Forissier cleanup:
20657901324dSJerome Forissier     return( ret );
2066817466cbSJens Wiklander }
2067817466cbSJens Wiklander 
2068817466cbSJens Wiklander /*
2069817466cbSJens Wiklander  * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
2070817466cbSJens Wiklander  */
20713d3b0591SJens Wiklander int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
20723d3b0591SJens Wiklander                          const mbedtls_mpi *E, const mbedtls_mpi *N,
2073*039e02dfSJerome Forissier                          mbedtls_mpi *prec_RR )
2074817466cbSJens Wiklander {
207511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2076817466cbSJens Wiklander     size_t wbits, wsize, one = 1;
2077817466cbSJens Wiklander     size_t i, j, nblimbs;
2078817466cbSJens Wiklander     size_t bufsize, nbits;
2079817466cbSJens Wiklander     mbedtls_mpi_uint ei, mm, state;
20807901324dSJerome Forissier     mbedtls_mpi RR, T, WW, Apos;
2081ad443200SJens Wiklander     mbedtls_mpi *W = NULL;
208241e5aa8fSJens Wiklander     const size_t array_size_W = 2 << MBEDTLS_MPI_WINDOW_SIZE;
2083817466cbSJens Wiklander     int neg;
2084817466cbSJens Wiklander 
20853d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
20863d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
20873d3b0591SJens Wiklander     MPI_VALIDATE_RET( E != NULL );
20883d3b0591SJens Wiklander     MPI_VALIDATE_RET( N != NULL );
20893d3b0591SJens Wiklander 
20903d3b0591SJens Wiklander     if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 )
2091817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2092817466cbSJens Wiklander 
2093817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )
2094817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2095817466cbSJens Wiklander 
20967901324dSJerome Forissier     if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS ||
20977901324dSJerome Forissier         mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS )
20987901324dSJerome Forissier         return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
20997901324dSJerome Forissier 
2100817466cbSJens Wiklander     /*
2101817466cbSJens Wiklander      * Init temps and window size
2102817466cbSJens Wiklander      */
21037901324dSJerome Forissier     mpi_montg_init( &mm, N );
21047901324dSJerome Forissier     mbedtls_mpi_init_mempool( &RR ); mbedtls_mpi_init( &T );
210598bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &Apos );
21067901324dSJerome Forissier     mbedtls_mpi_init_mempool( &WW );
2107817466cbSJens Wiklander 
2108817466cbSJens Wiklander     i = mbedtls_mpi_bitlen( E );
2109817466cbSJens Wiklander 
2110817466cbSJens Wiklander     wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
2111817466cbSJens Wiklander             ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
2112817466cbSJens Wiklander 
21135b25c76aSJerome Forissier #if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
2114817466cbSJens Wiklander     if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
2115817466cbSJens Wiklander         wsize = MBEDTLS_MPI_WINDOW_SIZE;
21165b25c76aSJerome Forissier #endif
2117817466cbSJens Wiklander 
2118817466cbSJens Wiklander     j = N->n + 1;
21197901324dSJerome Forissier     /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
21207901324dSJerome Forissier      * and mpi_montred() calls later. Here we ensure that W[1] and X are
21217901324dSJerome Forissier      * large enough, and later we'll grow other W[i] to the same length.
21227901324dSJerome Forissier      * They must not be shrunk midway through this function!
21237901324dSJerome Forissier      */
2124817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) );
2125ad443200SJens Wiklander 
2126817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) );
2127817466cbSJens Wiklander 
2128817466cbSJens Wiklander     /*
2129817466cbSJens Wiklander      * Compensate for negative A (and correct at the end)
2130817466cbSJens Wiklander      */
2131817466cbSJens Wiklander     neg = ( A->s == -1 );
2132817466cbSJens Wiklander     if( neg )
2133817466cbSJens Wiklander     {
2134817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) );
2135817466cbSJens Wiklander         Apos.s = 1;
2136817466cbSJens Wiklander         A = &Apos;
2137817466cbSJens Wiklander     }
2138817466cbSJens Wiklander 
2139817466cbSJens Wiklander     /*
2140817466cbSJens Wiklander      * If 1st call, pre-compute R^2 mod N
2141817466cbSJens Wiklander      */
2142*039e02dfSJerome Forissier     if( prec_RR == NULL || prec_RR->p == NULL )
2143817466cbSJens Wiklander     {
2144817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) );
2145817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) );
2146817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) );
2147817466cbSJens Wiklander 
2148*039e02dfSJerome Forissier         if( prec_RR != NULL )
2149*039e02dfSJerome Forissier             memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) );
2150817466cbSJens Wiklander     }
2151817466cbSJens Wiklander     else
2152*039e02dfSJerome Forissier         memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) );
2153817466cbSJens Wiklander 
2154ad443200SJens Wiklander     W = mempool_alloc( mbedtls_mpi_mempool,
2155ad443200SJens Wiklander                        sizeof( mbedtls_mpi ) * array_size_W );
2156ad443200SJens Wiklander     if( W == NULL ) {
2157ad443200SJens Wiklander         ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
2158ad443200SJens Wiklander         goto cleanup;
2159ad443200SJens Wiklander     }
2160ad443200SJens Wiklander     for( i = 0; i < array_size_W; i++ )
2161ad443200SJens Wiklander         mbedtls_mpi_init_mempool( W + i );
2162ad443200SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1],  j ) );
2163ad443200SJens Wiklander 
2164817466cbSJens Wiklander     /*
2165817466cbSJens Wiklander      * W[1] = A * R^2 * R^-1 mod N = A * R mod N
2166817466cbSJens Wiklander      */
2167817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 )
21687901324dSJerome Forissier     {
2169817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) );
21707901324dSJerome Forissier         /* This should be a no-op because W[1] is already that large before
21717901324dSJerome Forissier          * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
21727901324dSJerome Forissier          * in mpi_montmul() below, so let's make sure. */
21737901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) );
21747901324dSJerome Forissier     }
2175817466cbSJens Wiklander     else
2176817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) );
2177817466cbSJens Wiklander 
21787901324dSJerome Forissier     /* Note that this is safe because W[1] always has at least N->n limbs
21797901324dSJerome Forissier      * (it grew above and was preserved by mbedtls_mpi_copy()). */
21807901324dSJerome Forissier     mpi_montmul( &W[1], &RR, N, mm, &T );
2181817466cbSJens Wiklander 
2182817466cbSJens Wiklander     /*
2183817466cbSJens Wiklander      * X = R^2 * R^-1 mod N = R mod N
2184817466cbSJens Wiklander      */
2185817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) );
21867901324dSJerome Forissier     mpi_montred( X, N, mm, &T );
2187817466cbSJens Wiklander 
2188817466cbSJens Wiklander     if( wsize > 1 )
2189817466cbSJens Wiklander     {
2190817466cbSJens Wiklander         /*
2191817466cbSJens Wiklander          * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
2192817466cbSJens Wiklander          */
2193817466cbSJens Wiklander         j =  one << ( wsize - 1 );
2194817466cbSJens Wiklander 
2195817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) );
2196817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1]    ) );
2197817466cbSJens Wiklander 
2198817466cbSJens Wiklander         for( i = 0; i < wsize - 1; i++ )
21997901324dSJerome Forissier             mpi_montmul( &W[j], &W[j], N, mm, &T );
2200817466cbSJens Wiklander 
2201817466cbSJens Wiklander         /*
2202817466cbSJens Wiklander          * W[i] = W[i - 1] * W[1]
2203817466cbSJens Wiklander          */
2204817466cbSJens Wiklander         for( i = j + 1; i < ( one << wsize ); i++ )
2205817466cbSJens Wiklander         {
2206817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );
2207817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) );
2208817466cbSJens Wiklander 
22097901324dSJerome Forissier             mpi_montmul( &W[i], &W[1], N, mm, &T );
2210817466cbSJens Wiklander         }
2211817466cbSJens Wiklander     }
2212817466cbSJens Wiklander 
2213817466cbSJens Wiklander     nblimbs = E->n;
2214817466cbSJens Wiklander     bufsize = 0;
2215817466cbSJens Wiklander     nbits   = 0;
2216817466cbSJens Wiklander     wbits   = 0;
2217817466cbSJens Wiklander     state   = 0;
2218817466cbSJens Wiklander 
2219817466cbSJens Wiklander     while( 1 )
2220817466cbSJens Wiklander     {
2221817466cbSJens Wiklander         if( bufsize == 0 )
2222817466cbSJens Wiklander         {
2223817466cbSJens Wiklander             if( nblimbs == 0 )
2224817466cbSJens Wiklander                 break;
2225817466cbSJens Wiklander 
2226817466cbSJens Wiklander             nblimbs--;
2227817466cbSJens Wiklander 
2228817466cbSJens Wiklander             bufsize = sizeof( mbedtls_mpi_uint ) << 3;
2229817466cbSJens Wiklander         }
2230817466cbSJens Wiklander 
2231817466cbSJens Wiklander         bufsize--;
2232817466cbSJens Wiklander 
2233817466cbSJens Wiklander         ei = (E->p[nblimbs] >> bufsize) & 1;
2234817466cbSJens Wiklander 
2235817466cbSJens Wiklander         /*
2236817466cbSJens Wiklander          * skip leading 0s
2237817466cbSJens Wiklander          */
2238817466cbSJens Wiklander         if( ei == 0 && state == 0 )
2239817466cbSJens Wiklander             continue;
2240817466cbSJens Wiklander 
2241817466cbSJens Wiklander         if( ei == 0 && state == 1 )
2242817466cbSJens Wiklander         {
2243817466cbSJens Wiklander             /*
2244817466cbSJens Wiklander              * out of window, square X
2245817466cbSJens Wiklander              */
22467901324dSJerome Forissier             mpi_montmul( X, X, N, mm, &T );
2247817466cbSJens Wiklander             continue;
2248817466cbSJens Wiklander         }
2249817466cbSJens Wiklander 
2250817466cbSJens Wiklander         /*
2251817466cbSJens Wiklander          * add ei to current window
2252817466cbSJens Wiklander          */
2253817466cbSJens Wiklander         state = 2;
2254817466cbSJens Wiklander 
2255817466cbSJens Wiklander         nbits++;
2256817466cbSJens Wiklander         wbits |= ( ei << ( wsize - nbits ) );
2257817466cbSJens Wiklander 
2258817466cbSJens Wiklander         if( nbits == wsize )
2259817466cbSJens Wiklander         {
2260817466cbSJens Wiklander             /*
2261817466cbSJens Wiklander              * X = X^wsize R^-1 mod N
2262817466cbSJens Wiklander              */
2263817466cbSJens Wiklander             for( i = 0; i < wsize; i++ )
22647901324dSJerome Forissier                 mpi_montmul( X, X, N, mm, &T );
2265817466cbSJens Wiklander 
2266817466cbSJens Wiklander             /*
2267817466cbSJens Wiklander              * X = X * W[wbits] R^-1 mod N
2268817466cbSJens Wiklander              */
22697901324dSJerome Forissier             MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) );
22707901324dSJerome Forissier             mpi_montmul( X, &WW, N, mm, &T );
2271817466cbSJens Wiklander 
2272817466cbSJens Wiklander             state--;
2273817466cbSJens Wiklander             nbits = 0;
2274817466cbSJens Wiklander             wbits = 0;
2275817466cbSJens Wiklander         }
2276817466cbSJens Wiklander     }
2277817466cbSJens Wiklander 
2278817466cbSJens Wiklander     /*
2279817466cbSJens Wiklander      * process the remaining bits
2280817466cbSJens Wiklander      */
2281817466cbSJens Wiklander     for( i = 0; i < nbits; i++ )
2282817466cbSJens Wiklander     {
22837901324dSJerome Forissier         mpi_montmul( X, X, N, mm, &T );
2284817466cbSJens Wiklander 
2285817466cbSJens Wiklander         wbits <<= 1;
2286817466cbSJens Wiklander 
2287817466cbSJens Wiklander         if( ( wbits & ( one << wsize ) ) != 0 )
22887901324dSJerome Forissier             mpi_montmul( X, &W[1], N, mm, &T );
2289817466cbSJens Wiklander     }
2290817466cbSJens Wiklander 
2291817466cbSJens Wiklander     /*
2292817466cbSJens Wiklander      * X = A^E * R * R^-1 mod N = A^E mod N
2293817466cbSJens Wiklander      */
22947901324dSJerome Forissier     mpi_montred( X, N, mm, &T );
2295817466cbSJens Wiklander 
2296817466cbSJens Wiklander     if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )
2297817466cbSJens Wiklander     {
2298817466cbSJens Wiklander         X->s = -1;
2299817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) );
2300817466cbSJens Wiklander     }
2301817466cbSJens Wiklander 
2302817466cbSJens Wiklander cleanup:
2303817466cbSJens Wiklander 
2304ad443200SJens Wiklander     if( W )
230541e5aa8fSJens Wiklander         for( i = 0; i < array_size_W; i++ )
2306b99a4a18SJens Wiklander             mbedtls_mpi_free( W + i );
230741e5aa8fSJens Wiklander     mempool_free( mbedtls_mpi_mempool , W );
2308817466cbSJens Wiklander 
2309b99a4a18SJens Wiklander     mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos );
23107901324dSJerome Forissier     mbedtls_mpi_free( &WW );
2311817466cbSJens Wiklander 
2312*039e02dfSJerome Forissier     if( prec_RR == NULL || prec_RR->p == NULL )
2313817466cbSJens Wiklander         mbedtls_mpi_free( &RR );
2314817466cbSJens Wiklander 
2315817466cbSJens Wiklander     return( ret );
2316817466cbSJens Wiklander }
2317817466cbSJens Wiklander 
2318817466cbSJens Wiklander /*
2319817466cbSJens Wiklander  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
2320817466cbSJens Wiklander  */
2321817466cbSJens Wiklander int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
2322817466cbSJens Wiklander {
232311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2324817466cbSJens Wiklander     size_t lz, lzt;
232511fa71b9SJerome Forissier     mbedtls_mpi TA, TB;
2326817466cbSJens Wiklander 
23273d3b0591SJens Wiklander     MPI_VALIDATE_RET( G != NULL );
23283d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
23293d3b0591SJens Wiklander     MPI_VALIDATE_RET( B != NULL );
23303d3b0591SJens Wiklander 
233111fa71b9SJerome Forissier     mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB );
2332817466cbSJens Wiklander 
2333817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) );
2334817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) );
2335817466cbSJens Wiklander 
2336817466cbSJens Wiklander     lz = mbedtls_mpi_lsb( &TA );
2337817466cbSJens Wiklander     lzt = mbedtls_mpi_lsb( &TB );
2338817466cbSJens Wiklander 
23397901324dSJerome Forissier     /* The loop below gives the correct result when A==0 but not when B==0.
23407901324dSJerome Forissier      * So have a special case for B==0. Leverage the fact that we just
23417901324dSJerome Forissier      * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test
23427901324dSJerome Forissier      * slightly more efficient than cmp_int(). */
23437901324dSJerome Forissier     if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 )
23447901324dSJerome Forissier     {
23457901324dSJerome Forissier         ret = mbedtls_mpi_copy( G, A );
23467901324dSJerome Forissier         goto cleanup;
23477901324dSJerome Forissier     }
23487901324dSJerome Forissier 
2349817466cbSJens Wiklander     if( lzt < lz )
2350817466cbSJens Wiklander         lz = lzt;
2351817466cbSJens Wiklander 
2352817466cbSJens Wiklander     TA.s = TB.s = 1;
2353817466cbSJens Wiklander 
23547901324dSJerome Forissier     /* We mostly follow the procedure described in HAC 14.54, but with some
23557901324dSJerome Forissier      * minor differences:
23567901324dSJerome Forissier      * - Sequences of multiplications or divisions by 2 are grouped into a
23577901324dSJerome Forissier      *   single shift operation.
23587901324dSJerome Forissier      * - The procedure in HAC assumes that 0 < TB <= TA.
23597901324dSJerome Forissier      *     - The condition TB <= TA is not actually necessary for correctness.
23607901324dSJerome Forissier      *       TA and TB have symmetric roles except for the loop termination
23617901324dSJerome Forissier      *       condition, and the shifts at the beginning of the loop body
23627901324dSJerome Forissier      *       remove any significance from the ordering of TA vs TB before
23637901324dSJerome Forissier      *       the shifts.
23647901324dSJerome Forissier      *     - If TA = 0, the loop goes through 0 iterations and the result is
23657901324dSJerome Forissier      *       correctly TB.
23667901324dSJerome Forissier      *     - The case TB = 0 was short-circuited above.
23677901324dSJerome Forissier      *
23687901324dSJerome Forissier      * For the correctness proof below, decompose the original values of
23697901324dSJerome Forissier      * A and B as
23707901324dSJerome Forissier      *   A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1
23717901324dSJerome Forissier      *   B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1
23727901324dSJerome Forissier      * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'),
23737901324dSJerome Forissier      * and gcd(A',B') is odd or 0.
23747901324dSJerome Forissier      *
23757901324dSJerome Forissier      * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB).
23767901324dSJerome Forissier      * The code maintains the following invariant:
23777901324dSJerome Forissier      *     gcd(A,B) = 2^k * gcd(TA,TB) for some k   (I)
23787901324dSJerome Forissier      */
23797901324dSJerome Forissier 
23807901324dSJerome Forissier     /* Proof that the loop terminates:
23817901324dSJerome Forissier      * At each iteration, either the right-shift by 1 is made on a nonzero
23827901324dSJerome Forissier      * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases
23837901324dSJerome Forissier      * by at least 1, or the right-shift by 1 is made on zero and then
23847901324dSJerome Forissier      * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted
23857901324dSJerome Forissier      * since in that case TB is calculated from TB-TA with the condition TB>TA).
23867901324dSJerome Forissier      */
2387817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 )
2388817466cbSJens Wiklander     {
23897901324dSJerome Forissier         /* Divisions by 2 preserve the invariant (I). */
2390817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) );
2391817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) );
2392817466cbSJens Wiklander 
23937901324dSJerome Forissier         /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd,
23947901324dSJerome Forissier          * TA-TB is even so the division by 2 has an integer result.
23957901324dSJerome Forissier          * Invariant (I) is preserved since any odd divisor of both TA and TB
23967901324dSJerome Forissier          * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
2397*039e02dfSJerome Forissier          * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
23987901324dSJerome Forissier          * divides TA.
23997901324dSJerome Forissier          */
2400817466cbSJens Wiklander         if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
2401817466cbSJens Wiklander         {
2402817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) );
2403817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) );
2404817466cbSJens Wiklander         }
2405817466cbSJens Wiklander         else
2406817466cbSJens Wiklander         {
2407817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) );
2408817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) );
2409817466cbSJens Wiklander         }
24107901324dSJerome Forissier         /* Note that one of TA or TB is still odd. */
2411817466cbSJens Wiklander     }
2412817466cbSJens Wiklander 
24137901324dSJerome Forissier     /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k.
24147901324dSJerome Forissier      * At the loop exit, TA = 0, so gcd(TA,TB) = TB.
24157901324dSJerome Forissier      * - If there was at least one loop iteration, then one of TA or TB is odd,
24167901324dSJerome Forissier      *   and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case,
24177901324dSJerome Forissier      *   lz = min(a,b) so gcd(A,B) = 2^lz * TB.
24187901324dSJerome Forissier      * - If there was no loop iteration, then A was 0, and gcd(A,B) = B.
24197901324dSJerome Forissier      *   In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well.
24207901324dSJerome Forissier      */
24217901324dSJerome Forissier 
2422817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) );
2423817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) );
2424817466cbSJens Wiklander 
2425817466cbSJens Wiklander cleanup:
2426817466cbSJens Wiklander 
242711fa71b9SJerome Forissier     mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB );
2428817466cbSJens Wiklander 
2429817466cbSJens Wiklander     return( ret );
2430817466cbSJens Wiklander }
2431817466cbSJens Wiklander 
24327901324dSJerome Forissier /* Fill X with n_bytes random bytes.
24337901324dSJerome Forissier  * X must already have room for those bytes.
24347901324dSJerome Forissier  * The ordering of the bytes returned from the RNG is suitable for
24357901324dSJerome Forissier  * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()).
24367901324dSJerome Forissier  * The size and sign of X are unchanged.
24377901324dSJerome Forissier  * n_bytes must not be 0.
24387901324dSJerome Forissier  */
24397901324dSJerome Forissier static int mpi_fill_random_internal(
24407901324dSJerome Forissier     mbedtls_mpi *X, size_t n_bytes,
24417901324dSJerome Forissier     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
24427901324dSJerome Forissier {
24437901324dSJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
24447901324dSJerome Forissier     const size_t limbs = CHARS_TO_LIMBS( n_bytes );
24457901324dSJerome Forissier     const size_t overhead = ( limbs * ciL ) - n_bytes;
24467901324dSJerome Forissier 
24477901324dSJerome Forissier     if( X->n < limbs )
24487901324dSJerome Forissier         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
24497901324dSJerome Forissier 
24507901324dSJerome Forissier     memset( X->p, 0, overhead );
24517901324dSJerome Forissier     memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL );
24527901324dSJerome Forissier     MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) );
24537901324dSJerome Forissier     mpi_bigendian_to_host( X->p, limbs );
24547901324dSJerome Forissier 
24557901324dSJerome Forissier cleanup:
24567901324dSJerome Forissier     return( ret );
24577901324dSJerome Forissier }
24587901324dSJerome Forissier 
2459817466cbSJens Wiklander /*
2460817466cbSJens Wiklander  * Fill X with size bytes of random.
2461817466cbSJens Wiklander  *
2462817466cbSJens Wiklander  * Use a temporary bytes representation to make sure the result is the same
2463817466cbSJens Wiklander  * regardless of the platform endianness (useful when f_rng is actually
2464817466cbSJens Wiklander  * deterministic, eg for tests).
2465817466cbSJens Wiklander  */
2466817466cbSJens Wiklander int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
2467817466cbSJens Wiklander                      int (*f_rng)(void *, unsigned char *, size_t),
2468817466cbSJens Wiklander                      void *p_rng )
2469817466cbSJens Wiklander {
247011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
24715b25c76aSJerome Forissier     size_t const limbs = CHARS_TO_LIMBS( size );
24725b25c76aSJerome Forissier 
24733d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
24743d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
2475817466cbSJens Wiklander 
24765b25c76aSJerome Forissier     /* Ensure that target MPI has exactly the necessary number of limbs */
24777901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) );
24787901324dSJerome Forissier     if( size == 0 )
24797901324dSJerome Forissier         return( 0 );
2480817466cbSJens Wiklander 
24817901324dSJerome Forissier     ret = mpi_fill_random_internal( X, size, f_rng, p_rng );
2482817466cbSJens Wiklander 
2483817466cbSJens Wiklander cleanup:
2484817466cbSJens Wiklander     return( ret );
2485817466cbSJens Wiklander }
2486817466cbSJens Wiklander 
24877901324dSJerome Forissier int mbedtls_mpi_random( mbedtls_mpi *X,
24887901324dSJerome Forissier                         mbedtls_mpi_sint min,
24897901324dSJerome Forissier                         const mbedtls_mpi *N,
24907901324dSJerome Forissier                         int (*f_rng)(void *, unsigned char *, size_t),
24917901324dSJerome Forissier                         void *p_rng )
24927901324dSJerome Forissier {
24937901324dSJerome Forissier     int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
24947901324dSJerome Forissier     int count;
24957901324dSJerome Forissier     unsigned lt_lower = 1, lt_upper = 0;
24967901324dSJerome Forissier     size_t n_bits = mbedtls_mpi_bitlen( N );
24977901324dSJerome Forissier     size_t n_bytes = ( n_bits + 7 ) / 8;
24987901324dSJerome Forissier     mbedtls_mpi lower_bound;
24997901324dSJerome Forissier 
25007901324dSJerome Forissier     if( min < 0 )
25017901324dSJerome Forissier         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
25027901324dSJerome Forissier     if( mbedtls_mpi_cmp_int( N, min ) <= 0 )
25037901324dSJerome Forissier         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
25047901324dSJerome Forissier 
25057901324dSJerome Forissier     /*
25067901324dSJerome Forissier      * When min == 0, each try has at worst a probability 1/2 of failing
25077901324dSJerome Forissier      * (the msb has a probability 1/2 of being 0, and then the result will
25087901324dSJerome Forissier      * be < N), so after 30 tries failure probability is a most 2**(-30).
25097901324dSJerome Forissier      *
25107901324dSJerome Forissier      * When N is just below a power of 2, as is the case when generating
25117901324dSJerome Forissier      * a random scalar on most elliptic curves, 1 try is enough with
25127901324dSJerome Forissier      * overwhelming probability. When N is just above a power of 2,
25137901324dSJerome Forissier      * as when generating a random scalar on secp224k1, each try has
25147901324dSJerome Forissier      * a probability of failing that is almost 1/2.
25157901324dSJerome Forissier      *
25167901324dSJerome Forissier      * The probabilities are almost the same if min is nonzero but negligible
25177901324dSJerome Forissier      * compared to N. This is always the case when N is crypto-sized, but
25187901324dSJerome Forissier      * it's convenient to support small N for testing purposes. When N
25197901324dSJerome Forissier      * is small, use a higher repeat count, otherwise the probability of
25207901324dSJerome Forissier      * failure is macroscopic.
25217901324dSJerome Forissier      */
25227901324dSJerome Forissier     count = ( n_bytes > 4 ? 30 : 250 );
25237901324dSJerome Forissier 
25247901324dSJerome Forissier     mbedtls_mpi_init( &lower_bound );
25257901324dSJerome Forissier 
25267901324dSJerome Forissier     /* Ensure that target MPI has exactly the same number of limbs
25277901324dSJerome Forissier      * as the upper bound, even if the upper bound has leading zeros.
25287901324dSJerome Forissier      * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */
25297901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) );
25307901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) );
25317901324dSJerome Forissier     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) );
25327901324dSJerome Forissier 
25337901324dSJerome Forissier     /*
25347901324dSJerome Forissier      * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA)
25357901324dSJerome Forissier      * when f_rng is a suitably parametrized instance of HMAC_DRBG:
25367901324dSJerome Forissier      * - use the same byte ordering;
25377901324dSJerome Forissier      * - keep the leftmost n_bits bits of the generated octet string;
25387901324dSJerome Forissier      * - try until result is in the desired range.
25397901324dSJerome Forissier      * This also avoids any bias, which is especially important for ECDSA.
25407901324dSJerome Forissier      */
25417901324dSJerome Forissier     do
25427901324dSJerome Forissier     {
25437901324dSJerome Forissier         MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) );
25447901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) );
25457901324dSJerome Forissier 
25467901324dSJerome Forissier         if( --count == 0 )
25477901324dSJerome Forissier         {
25487901324dSJerome Forissier             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
25497901324dSJerome Forissier             goto cleanup;
25507901324dSJerome Forissier         }
25517901324dSJerome Forissier 
25527901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, &lt_lower ) );
25537901324dSJerome Forissier         MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, &lt_upper ) );
25547901324dSJerome Forissier     }
25557901324dSJerome Forissier     while( lt_lower != 0 || lt_upper == 0 );
25567901324dSJerome Forissier 
25577901324dSJerome Forissier cleanup:
25587901324dSJerome Forissier     mbedtls_mpi_free( &lower_bound );
25597901324dSJerome Forissier     return( ret );
25607901324dSJerome Forissier }
25617901324dSJerome Forissier 
2562817466cbSJens Wiklander /*
2563817466cbSJens Wiklander  * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
2564817466cbSJens Wiklander  */
2565817466cbSJens Wiklander int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
2566817466cbSJens Wiklander {
256711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2568817466cbSJens Wiklander     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
25693d3b0591SJens Wiklander     MPI_VALIDATE_RET( X != NULL );
25703d3b0591SJens Wiklander     MPI_VALIDATE_RET( A != NULL );
25713d3b0591SJens Wiklander     MPI_VALIDATE_RET( N != NULL );
2572817466cbSJens Wiklander 
2573817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 )
2574817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2575817466cbSJens Wiklander 
257698bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TU );
257798bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &U1 ); mbedtls_mpi_init_mempool( &U2 );
257898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &G ); mbedtls_mpi_init_mempool( &TB );
257998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &TV ); mbedtls_mpi_init_mempool( &V1 );
258098bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &V2 );
2581817466cbSJens Wiklander 
2582817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) );
2583817466cbSJens Wiklander 
2584817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
2585817466cbSJens Wiklander     {
2586817466cbSJens Wiklander         ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2587817466cbSJens Wiklander         goto cleanup;
2588817466cbSJens Wiklander     }
2589817466cbSJens Wiklander 
2590817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) );
2591817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) );
2592817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) );
2593817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) );
2594817466cbSJens Wiklander 
2595817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) );
2596817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) );
2597817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) );
2598817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) );
2599817466cbSJens Wiklander 
2600817466cbSJens Wiklander     do
2601817466cbSJens Wiklander     {
2602817466cbSJens Wiklander         while( ( TU.p[0] & 1 ) == 0 )
2603817466cbSJens Wiklander         {
2604817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) );
2605817466cbSJens Wiklander 
2606817466cbSJens Wiklander             if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
2607817466cbSJens Wiklander             {
2608817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) );
2609817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) );
2610817466cbSJens Wiklander             }
2611817466cbSJens Wiklander 
2612817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) );
2613817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) );
2614817466cbSJens Wiklander         }
2615817466cbSJens Wiklander 
2616817466cbSJens Wiklander         while( ( TV.p[0] & 1 ) == 0 )
2617817466cbSJens Wiklander         {
2618817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) );
2619817466cbSJens Wiklander 
2620817466cbSJens Wiklander             if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
2621817466cbSJens Wiklander             {
2622817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) );
2623817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) );
2624817466cbSJens Wiklander             }
2625817466cbSJens Wiklander 
2626817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) );
2627817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) );
2628817466cbSJens Wiklander         }
2629817466cbSJens Wiklander 
2630817466cbSJens Wiklander         if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 )
2631817466cbSJens Wiklander         {
2632817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) );
2633817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) );
2634817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) );
2635817466cbSJens Wiklander         }
2636817466cbSJens Wiklander         else
2637817466cbSJens Wiklander         {
2638817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) );
2639817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) );
2640817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) );
2641817466cbSJens Wiklander         }
2642817466cbSJens Wiklander     }
2643817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 );
2644817466cbSJens Wiklander 
2645817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 )
2646817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) );
2647817466cbSJens Wiklander 
2648817466cbSJens Wiklander     while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 )
2649817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) );
2650817466cbSJens Wiklander 
2651817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) );
2652817466cbSJens Wiklander 
2653817466cbSJens Wiklander cleanup:
2654817466cbSJens Wiklander 
2655817466cbSJens Wiklander     mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 );
2656817466cbSJens Wiklander     mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV );
2657817466cbSJens Wiklander     mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 );
2658817466cbSJens Wiklander 
2659817466cbSJens Wiklander     return( ret );
2660817466cbSJens Wiklander }
2661817466cbSJens Wiklander 
2662817466cbSJens Wiklander #if defined(MBEDTLS_GENPRIME)
2663817466cbSJens Wiklander 
2664817466cbSJens Wiklander static const int small_prime[] =
2665817466cbSJens Wiklander {
2666817466cbSJens Wiklander         3,    5,    7,   11,   13,   17,   19,   23,
2667817466cbSJens Wiklander        29,   31,   37,   41,   43,   47,   53,   59,
2668817466cbSJens Wiklander        61,   67,   71,   73,   79,   83,   89,   97,
2669817466cbSJens Wiklander       101,  103,  107,  109,  113,  127,  131,  137,
2670817466cbSJens Wiklander       139,  149,  151,  157,  163,  167,  173,  179,
2671817466cbSJens Wiklander       181,  191,  193,  197,  199,  211,  223,  227,
2672817466cbSJens Wiklander       229,  233,  239,  241,  251,  257,  263,  269,
2673817466cbSJens Wiklander       271,  277,  281,  283,  293,  307,  311,  313,
2674817466cbSJens Wiklander       317,  331,  337,  347,  349,  353,  359,  367,
2675817466cbSJens Wiklander       373,  379,  383,  389,  397,  401,  409,  419,
2676817466cbSJens Wiklander       421,  431,  433,  439,  443,  449,  457,  461,
2677817466cbSJens Wiklander       463,  467,  479,  487,  491,  499,  503,  509,
2678817466cbSJens Wiklander       521,  523,  541,  547,  557,  563,  569,  571,
2679817466cbSJens Wiklander       577,  587,  593,  599,  601,  607,  613,  617,
2680817466cbSJens Wiklander       619,  631,  641,  643,  647,  653,  659,  661,
2681817466cbSJens Wiklander       673,  677,  683,  691,  701,  709,  719,  727,
2682817466cbSJens Wiklander       733,  739,  743,  751,  757,  761,  769,  773,
2683817466cbSJens Wiklander       787,  797,  809,  811,  821,  823,  827,  829,
2684817466cbSJens Wiklander       839,  853,  857,  859,  863,  877,  881,  883,
2685817466cbSJens Wiklander       887,  907,  911,  919,  929,  937,  941,  947,
2686817466cbSJens Wiklander       953,  967,  971,  977,  983,  991,  997, -103
2687817466cbSJens Wiklander };
2688817466cbSJens Wiklander 
2689817466cbSJens Wiklander /*
2690817466cbSJens Wiklander  * Small divisors test (X must be positive)
2691817466cbSJens Wiklander  *
2692817466cbSJens Wiklander  * Return values:
2693817466cbSJens Wiklander  * 0: no small factor (possible prime, more tests needed)
2694817466cbSJens Wiklander  * 1: certain prime
2695817466cbSJens Wiklander  * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime
2696817466cbSJens Wiklander  * other negative: error
2697817466cbSJens Wiklander  */
2698817466cbSJens Wiklander static int mpi_check_small_factors( const mbedtls_mpi *X )
2699817466cbSJens Wiklander {
2700817466cbSJens Wiklander     int ret = 0;
2701817466cbSJens Wiklander     size_t i;
2702817466cbSJens Wiklander     mbedtls_mpi_uint r;
2703817466cbSJens Wiklander 
2704817466cbSJens Wiklander     if( ( X->p[0] & 1 ) == 0 )
2705817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2706817466cbSJens Wiklander 
2707817466cbSJens Wiklander     for( i = 0; small_prime[i] > 0; i++ )
2708817466cbSJens Wiklander     {
2709817466cbSJens Wiklander         if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 )
2710817466cbSJens Wiklander             return( 1 );
2711817466cbSJens Wiklander 
2712817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) );
2713817466cbSJens Wiklander 
2714817466cbSJens Wiklander         if( r == 0 )
2715817466cbSJens Wiklander             return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2716817466cbSJens Wiklander     }
2717817466cbSJens Wiklander 
2718817466cbSJens Wiklander cleanup:
2719817466cbSJens Wiklander     return( ret );
2720817466cbSJens Wiklander }
2721817466cbSJens Wiklander 
2722817466cbSJens Wiklander /*
2723817466cbSJens Wiklander  * Miller-Rabin pseudo-primality test  (HAC 4.24)
2724817466cbSJens Wiklander  */
27253d3b0591SJens Wiklander static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
2726817466cbSJens Wiklander                              int (*f_rng)(void *, unsigned char *, size_t),
2727817466cbSJens Wiklander                              void *p_rng )
2728817466cbSJens Wiklander {
2729817466cbSJens Wiklander     int ret, count;
27303d3b0591SJens Wiklander     size_t i, j, k, s;
2731817466cbSJens Wiklander     mbedtls_mpi W, R, T, A, RR;
2732817466cbSJens Wiklander 
27333d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
27343d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
27353d3b0591SJens Wiklander 
273698bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &W ); mbedtls_mpi_init_mempool( &R );
273798bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &T ); mbedtls_mpi_init_mempool( &A );
273898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &RR );
2739817466cbSJens Wiklander 
2740817466cbSJens Wiklander     /*
2741817466cbSJens Wiklander      * W = |X| - 1
2742817466cbSJens Wiklander      * R = W >> lsb( W )
2743817466cbSJens Wiklander      */
2744817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) );
2745817466cbSJens Wiklander     s = mbedtls_mpi_lsb( &W );
2746817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) );
2747817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
2748817466cbSJens Wiklander 
27493d3b0591SJens Wiklander     for( i = 0; i < rounds; i++ )
2750817466cbSJens Wiklander     {
2751817466cbSJens Wiklander         /*
2752817466cbSJens Wiklander          * pick a random A, 1 < A < |X| - 1
2753817466cbSJens Wiklander          */
2754817466cbSJens Wiklander         count = 0;
2755817466cbSJens Wiklander         do {
2756817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
2757817466cbSJens Wiklander 
2758817466cbSJens Wiklander             j = mbedtls_mpi_bitlen( &A );
2759817466cbSJens Wiklander             k = mbedtls_mpi_bitlen( &W );
2760817466cbSJens Wiklander             if (j > k) {
27613d3b0591SJens Wiklander                 A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
2762817466cbSJens Wiklander             }
2763817466cbSJens Wiklander 
2764117cce93SJens Wiklander             if (count++ > 300) {
2765336e3299SJens Wiklander                 ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2766336e3299SJens Wiklander                 goto cleanup;
2767817466cbSJens Wiklander             }
2768817466cbSJens Wiklander 
2769817466cbSJens Wiklander         } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
2770817466cbSJens Wiklander                   mbedtls_mpi_cmp_int( &A, 1 )  <= 0    );
2771817466cbSJens Wiklander 
2772817466cbSJens Wiklander         /*
2773817466cbSJens Wiklander          * A = A^R mod |X|
2774817466cbSJens Wiklander          */
2775817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) );
2776817466cbSJens Wiklander 
2777817466cbSJens Wiklander         if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 ||
2778817466cbSJens Wiklander             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
2779817466cbSJens Wiklander             continue;
2780817466cbSJens Wiklander 
2781817466cbSJens Wiklander         j = 1;
2782817466cbSJens Wiklander         while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 )
2783817466cbSJens Wiklander         {
2784817466cbSJens Wiklander             /*
2785817466cbSJens Wiklander              * A = A * A mod |X|
2786817466cbSJens Wiklander              */
2787817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) );
2788817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X  ) );
2789817466cbSJens Wiklander 
2790817466cbSJens Wiklander             if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 )
2791817466cbSJens Wiklander                 break;
2792817466cbSJens Wiklander 
2793817466cbSJens Wiklander             j++;
2794817466cbSJens Wiklander         }
2795817466cbSJens Wiklander 
2796817466cbSJens Wiklander         /*
2797817466cbSJens Wiklander          * not prime if A != |X| - 1 or A == 1
2798817466cbSJens Wiklander          */
2799817466cbSJens Wiklander         if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ||
2800817466cbSJens Wiklander             mbedtls_mpi_cmp_int( &A,  1 ) == 0 )
2801817466cbSJens Wiklander         {
2802817466cbSJens Wiklander             ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2803817466cbSJens Wiklander             break;
2804817466cbSJens Wiklander         }
2805817466cbSJens Wiklander     }
2806817466cbSJens Wiklander 
2807817466cbSJens Wiklander cleanup:
28083d3b0591SJens Wiklander     mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R );
28093d3b0591SJens Wiklander     mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A );
2810817466cbSJens Wiklander     mbedtls_mpi_free( &RR );
2811817466cbSJens Wiklander 
2812817466cbSJens Wiklander     return( ret );
2813817466cbSJens Wiklander }
2814817466cbSJens Wiklander 
2815817466cbSJens Wiklander /*
2816817466cbSJens Wiklander  * Pseudo-primality test: small factors, then Miller-Rabin
2817817466cbSJens Wiklander  */
28183d3b0591SJens Wiklander int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
2819817466cbSJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t),
2820817466cbSJens Wiklander                               void *p_rng )
2821817466cbSJens Wiklander {
282211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2823817466cbSJens Wiklander     mbedtls_mpi XX;
28243d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
28253d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
2826817466cbSJens Wiklander 
2827817466cbSJens Wiklander     XX.s = 1;
2828817466cbSJens Wiklander     XX.n = X->n;
2829817466cbSJens Wiklander     XX.p = X->p;
2830817466cbSJens Wiklander 
2831817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 ||
2832817466cbSJens Wiklander         mbedtls_mpi_cmp_int( &XX, 1 ) == 0 )
2833817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
2834817466cbSJens Wiklander 
2835817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 )
2836817466cbSJens Wiklander         return( 0 );
2837817466cbSJens Wiklander 
2838817466cbSJens Wiklander     if( ( ret = mpi_check_small_factors( &XX ) ) != 0 )
2839817466cbSJens Wiklander     {
2840817466cbSJens Wiklander         if( ret == 1 )
2841817466cbSJens Wiklander             return( 0 );
2842817466cbSJens Wiklander 
2843817466cbSJens Wiklander         return( ret );
2844817466cbSJens Wiklander     }
2845817466cbSJens Wiklander 
28463d3b0591SJens Wiklander     return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
2847817466cbSJens Wiklander }
2848817466cbSJens Wiklander 
28493d3b0591SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED)
2850817466cbSJens Wiklander /*
28513d3b0591SJens Wiklander  * Pseudo-primality test, error probability 2^-80
2852817466cbSJens Wiklander  */
28533d3b0591SJens Wiklander int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
2854817466cbSJens Wiklander                   int (*f_rng)(void *, unsigned char *, size_t),
2855817466cbSJens Wiklander                   void *p_rng )
2856817466cbSJens Wiklander {
28573d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
28583d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
28593d3b0591SJens Wiklander 
28603d3b0591SJens Wiklander     /*
28613d3b0591SJens Wiklander      * In the past our key generation aimed for an error rate of at most
28623d3b0591SJens Wiklander      * 2^-80. Since this function is deprecated, aim for the same certainty
28633d3b0591SJens Wiklander      * here as well.
28643d3b0591SJens Wiklander      */
28653d3b0591SJens Wiklander     return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) );
28663d3b0591SJens Wiklander }
28673d3b0591SJens Wiklander #endif
28683d3b0591SJens Wiklander 
28693d3b0591SJens Wiklander /*
28703d3b0591SJens Wiklander  * Prime number generation
28713d3b0591SJens Wiklander  *
28723d3b0591SJens Wiklander  * To generate an RSA key in a way recommended by FIPS 186-4, both primes must
28733d3b0591SJens Wiklander  * be either 1024 bits or 1536 bits long, and flags must contain
28743d3b0591SJens Wiklander  * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR.
28753d3b0591SJens Wiklander  */
28763d3b0591SJens Wiklander int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags,
28773d3b0591SJens Wiklander                    int (*f_rng)(void *, unsigned char *, size_t),
28783d3b0591SJens Wiklander                    void *p_rng )
28793d3b0591SJens Wiklander {
28803d3b0591SJens Wiklander #ifdef MBEDTLS_HAVE_INT64
28813d3b0591SJens Wiklander // ceil(2^63.5)
28823d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL
28833d3b0591SJens Wiklander #else
28843d3b0591SJens Wiklander // ceil(2^31.5)
28853d3b0591SJens Wiklander #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U
28863d3b0591SJens Wiklander #endif
28873d3b0591SJens Wiklander     int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
2888817466cbSJens Wiklander     size_t k, n;
28893d3b0591SJens Wiklander     int rounds;
2890817466cbSJens Wiklander     mbedtls_mpi_uint r;
2891817466cbSJens Wiklander     mbedtls_mpi Y;
2892817466cbSJens Wiklander 
28933d3b0591SJens Wiklander     MPI_VALIDATE_RET( X     != NULL );
28943d3b0591SJens Wiklander     MPI_VALIDATE_RET( f_rng != NULL );
28953d3b0591SJens Wiklander 
2896817466cbSJens Wiklander     if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS )
2897817466cbSJens Wiklander         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
2898817466cbSJens Wiklander 
289998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &Y );
2900817466cbSJens Wiklander 
2901817466cbSJens Wiklander     n = BITS_TO_LIMBS( nbits );
2902817466cbSJens Wiklander 
29033d3b0591SJens Wiklander     if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 )
29043d3b0591SJens Wiklander     {
29053d3b0591SJens Wiklander         /*
29063d3b0591SJens Wiklander          * 2^-80 error probability, number of rounds chosen per HAC, table 4.4
29073d3b0591SJens Wiklander          */
29083d3b0591SJens Wiklander         rounds = ( ( nbits >= 1300 ) ?  2 : ( nbits >=  850 ) ?  3 :
29093d3b0591SJens Wiklander                    ( nbits >=  650 ) ?  4 : ( nbits >=  350 ) ?  8 :
29103d3b0591SJens Wiklander                    ( nbits >=  250 ) ? 12 : ( nbits >=  150 ) ? 18 : 27 );
29113d3b0591SJens Wiklander     }
29123d3b0591SJens Wiklander     else
29133d3b0591SJens Wiklander     {
29143d3b0591SJens Wiklander         /*
29153d3b0591SJens Wiklander          * 2^-100 error probability, number of rounds computed based on HAC,
29163d3b0591SJens Wiklander          * fact 4.48
29173d3b0591SJens Wiklander          */
29183d3b0591SJens Wiklander         rounds = ( ( nbits >= 1450 ) ?  4 : ( nbits >=  1150 ) ?  5 :
29193d3b0591SJens Wiklander                    ( nbits >= 1000 ) ?  6 : ( nbits >=   850 ) ?  7 :
29203d3b0591SJens Wiklander                    ( nbits >=  750 ) ?  8 : ( nbits >=   500 ) ? 13 :
29213d3b0591SJens Wiklander                    ( nbits >=  250 ) ? 28 : ( nbits >=   150 ) ? 40 : 51 );
29223d3b0591SJens Wiklander     }
29233d3b0591SJens Wiklander 
29243d3b0591SJens Wiklander     while( 1 )
29253d3b0591SJens Wiklander     {
2926817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
29273d3b0591SJens Wiklander         /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */
29283d3b0591SJens Wiklander         if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue;
2929817466cbSJens Wiklander 
29303d3b0591SJens Wiklander         k = n * biL;
29313d3b0591SJens Wiklander         if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) );
2932817466cbSJens Wiklander         X->p[0] |= 1;
2933817466cbSJens Wiklander 
29343d3b0591SJens Wiklander         if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 )
2935817466cbSJens Wiklander         {
29363d3b0591SJens Wiklander             ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng );
29373d3b0591SJens Wiklander 
2938817466cbSJens Wiklander             if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2939817466cbSJens Wiklander                 goto cleanup;
2940817466cbSJens Wiklander         }
2941817466cbSJens Wiklander         else
2942817466cbSJens Wiklander         {
2943817466cbSJens Wiklander             /*
2944817466cbSJens Wiklander              * An necessary condition for Y and X = 2Y + 1 to be prime
2945817466cbSJens Wiklander              * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3).
2946817466cbSJens Wiklander              * Make sure it is satisfied, while keeping X = 3 mod 4
2947817466cbSJens Wiklander              */
2948817466cbSJens Wiklander 
2949817466cbSJens Wiklander             X->p[0] |= 2;
2950817466cbSJens Wiklander 
2951817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) );
2952817466cbSJens Wiklander             if( r == 0 )
2953817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) );
2954817466cbSJens Wiklander             else if( r == 1 )
2955817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) );
2956817466cbSJens Wiklander 
2957817466cbSJens Wiklander             /* Set Y = (X-1) / 2, which is X / 2 because X is odd */
2958817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) );
2959817466cbSJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) );
2960817466cbSJens Wiklander 
2961817466cbSJens Wiklander             while( 1 )
2962817466cbSJens Wiklander             {
2963817466cbSJens Wiklander                 /*
2964817466cbSJens Wiklander                  * First, check small factors for X and Y
2965817466cbSJens Wiklander                  * before doing Miller-Rabin on any of them
2966817466cbSJens Wiklander                  */
2967817466cbSJens Wiklander                 if( ( ret = mpi_check_small_factors(  X         ) ) == 0 &&
2968817466cbSJens Wiklander                     ( ret = mpi_check_small_factors( &Y         ) ) == 0 &&
29693d3b0591SJens Wiklander                     ( ret = mpi_miller_rabin(  X, rounds, f_rng, p_rng  ) )
29703d3b0591SJens Wiklander                                                                     == 0 &&
29713d3b0591SJens Wiklander                     ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng  ) )
29723d3b0591SJens Wiklander                                                                     == 0 )
29733d3b0591SJens Wiklander                     goto cleanup;
2974817466cbSJens Wiklander 
2975817466cbSJens Wiklander                 if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
2976817466cbSJens Wiklander                     goto cleanup;
2977817466cbSJens Wiklander 
2978817466cbSJens Wiklander                 /*
2979817466cbSJens Wiklander                  * Next candidates. We want to preserve Y = (X-1) / 2 and
2980817466cbSJens Wiklander                  * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3)
2981817466cbSJens Wiklander                  * so up Y by 6 and X by 12.
2982817466cbSJens Wiklander                  */
2983817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(  X,  X, 12 ) );
2984817466cbSJens Wiklander                 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6  ) );
2985817466cbSJens Wiklander             }
2986817466cbSJens Wiklander         }
29873d3b0591SJens Wiklander     }
2988817466cbSJens Wiklander 
2989817466cbSJens Wiklander cleanup:
2990817466cbSJens Wiklander 
2991817466cbSJens Wiklander     mbedtls_mpi_free( &Y );
2992817466cbSJens Wiklander 
2993817466cbSJens Wiklander     return( ret );
2994817466cbSJens Wiklander }
2995817466cbSJens Wiklander 
2996817466cbSJens Wiklander #endif /* MBEDTLS_GENPRIME */
2997817466cbSJens Wiklander 
2998817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
2999817466cbSJens Wiklander 
3000817466cbSJens Wiklander #define GCD_PAIR_COUNT  3
3001817466cbSJens Wiklander 
3002817466cbSJens Wiklander static const int gcd_pairs[GCD_PAIR_COUNT][3] =
3003817466cbSJens Wiklander {
3004817466cbSJens Wiklander     { 693, 609, 21 },
3005817466cbSJens Wiklander     { 1764, 868, 28 },
3006817466cbSJens Wiklander     { 768454923, 542167814, 1 }
3007817466cbSJens Wiklander };
3008817466cbSJens Wiklander 
3009817466cbSJens Wiklander /*
3010817466cbSJens Wiklander  * Checkup routine
3011817466cbSJens Wiklander  */
3012817466cbSJens Wiklander int mbedtls_mpi_self_test( int verbose )
3013817466cbSJens Wiklander {
3014817466cbSJens Wiklander     int ret, i;
3015817466cbSJens Wiklander     mbedtls_mpi A, E, N, X, Y, U, V;
3016817466cbSJens Wiklander 
301798bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &A ); mbedtls_mpi_init_mempool( &E );
301898bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &N ); mbedtls_mpi_init_mempool( &X );
301998bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &Y ); mbedtls_mpi_init_mempool( &U );
302098bd5fe3SJens Wiklander     mbedtls_mpi_init_mempool( &V );
3021817466cbSJens Wiklander 
3022817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16,
3023817466cbSJens Wiklander         "EFE021C2645FD1DC586E69184AF4A31E" \
3024817466cbSJens Wiklander         "D5F53E93B5F123FA41680867BA110131" \
3025817466cbSJens Wiklander         "944FE7952E2517337780CB0DB80E61AA" \
3026817466cbSJens Wiklander         "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
3027817466cbSJens Wiklander 
3028817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16,
3029817466cbSJens Wiklander         "B2E7EFD37075B9F03FF989C7C5051C20" \
3030817466cbSJens Wiklander         "34D2A323810251127E7BF8625A4F49A5" \
3031817466cbSJens Wiklander         "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
3032817466cbSJens Wiklander         "5B5C25763222FEFCCFC38B832366C29E" ) );
3033817466cbSJens Wiklander 
3034817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16,
3035817466cbSJens Wiklander         "0066A198186C18C10B2F5ED9B522752A" \
3036817466cbSJens Wiklander         "9830B69916E535C8F047518A889A43A5" \
3037817466cbSJens Wiklander         "94B6BED27A168D31D4A52F88925AA8F5" ) );
3038817466cbSJens Wiklander 
3039817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) );
3040817466cbSJens Wiklander 
3041817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3042817466cbSJens Wiklander         "602AB7ECA597A3D6B56FF9829A5E8B85" \
3043817466cbSJens Wiklander         "9E857EA95A03512E2BAE7391688D264A" \
3044817466cbSJens Wiklander         "A5663B0341DB9CCFD2C4C5F421FEC814" \
3045817466cbSJens Wiklander         "8001B72E848A38CAE1C65F78E56ABDEF" \
3046817466cbSJens Wiklander         "E12D3C039B8A02D6BE593F0BBBDA56F1" \
3047817466cbSJens Wiklander         "ECF677152EF804370C1A305CAF3B5BF1" \
3048817466cbSJens Wiklander         "30879B56C61DE584A0F53A2447A51E" ) );
3049817466cbSJens Wiklander 
3050817466cbSJens Wiklander     if( verbose != 0 )
3051817466cbSJens Wiklander         mbedtls_printf( "  MPI test #1 (mul_mpi): " );
3052817466cbSJens Wiklander 
3053817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3054817466cbSJens Wiklander     {
3055817466cbSJens Wiklander         if( verbose != 0 )
3056817466cbSJens Wiklander             mbedtls_printf( "failed\n" );
3057817466cbSJens Wiklander 
3058817466cbSJens Wiklander         ret = 1;
3059817466cbSJens Wiklander         goto cleanup;
3060817466cbSJens Wiklander     }
3061817466cbSJens Wiklander 
3062817466cbSJens Wiklander     if( verbose != 0 )
3063817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3064817466cbSJens Wiklander 
3065817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) );
3066817466cbSJens Wiklander 
3067817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3068817466cbSJens Wiklander         "256567336059E52CAE22925474705F39A94" ) );
3069817466cbSJens Wiklander 
3070817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16,
3071817466cbSJens Wiklander         "6613F26162223DF488E9CD48CC132C7A" \
3072817466cbSJens Wiklander         "0AC93C701B001B092E4E5B9F73BCD27B" \
3073817466cbSJens Wiklander         "9EE50D0657C77F374E903CDFA4C642" ) );
3074817466cbSJens Wiklander 
3075817466cbSJens Wiklander     if( verbose != 0 )
3076817466cbSJens Wiklander         mbedtls_printf( "  MPI test #2 (div_mpi): " );
3077817466cbSJens Wiklander 
3078817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ||
3079817466cbSJens Wiklander         mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 )
3080817466cbSJens Wiklander     {
3081817466cbSJens Wiklander         if( verbose != 0 )
3082817466cbSJens Wiklander             mbedtls_printf( "failed\n" );
3083817466cbSJens Wiklander 
3084817466cbSJens Wiklander         ret = 1;
3085817466cbSJens Wiklander         goto cleanup;
3086817466cbSJens Wiklander     }
3087817466cbSJens Wiklander 
3088817466cbSJens Wiklander     if( verbose != 0 )
3089817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3090817466cbSJens Wiklander 
3091817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) );
3092817466cbSJens Wiklander 
3093817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3094817466cbSJens Wiklander         "36E139AEA55215609D2816998ED020BB" \
3095817466cbSJens Wiklander         "BD96C37890F65171D948E9BC7CBAA4D9" \
3096817466cbSJens Wiklander         "325D24D6A3C12710F10A09FA08AB87" ) );
3097817466cbSJens Wiklander 
3098817466cbSJens Wiklander     if( verbose != 0 )
3099817466cbSJens Wiklander         mbedtls_printf( "  MPI test #3 (exp_mod): " );
3100817466cbSJens Wiklander 
3101817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3102817466cbSJens Wiklander     {
3103817466cbSJens Wiklander         if( verbose != 0 )
3104817466cbSJens Wiklander             mbedtls_printf( "failed\n" );
3105817466cbSJens Wiklander 
3106817466cbSJens Wiklander         ret = 1;
3107817466cbSJens Wiklander         goto cleanup;
3108817466cbSJens Wiklander     }
3109817466cbSJens Wiklander 
3110817466cbSJens Wiklander     if( verbose != 0 )
3111817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3112817466cbSJens Wiklander 
3113817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) );
3114817466cbSJens Wiklander 
3115817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16,
3116817466cbSJens Wiklander         "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
3117817466cbSJens Wiklander         "C3DBA76456363A10869622EAC2DD84EC" \
3118817466cbSJens Wiklander         "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
3119817466cbSJens Wiklander 
3120817466cbSJens Wiklander     if( verbose != 0 )
3121817466cbSJens Wiklander         mbedtls_printf( "  MPI test #4 (inv_mod): " );
3122817466cbSJens Wiklander 
3123817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 )
3124817466cbSJens Wiklander     {
3125817466cbSJens Wiklander         if( verbose != 0 )
3126817466cbSJens Wiklander             mbedtls_printf( "failed\n" );
3127817466cbSJens Wiklander 
3128817466cbSJens Wiklander         ret = 1;
3129817466cbSJens Wiklander         goto cleanup;
3130817466cbSJens Wiklander     }
3131817466cbSJens Wiklander 
3132817466cbSJens Wiklander     if( verbose != 0 )
3133817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3134817466cbSJens Wiklander 
3135817466cbSJens Wiklander     if( verbose != 0 )
3136817466cbSJens Wiklander         mbedtls_printf( "  MPI test #5 (simple gcd): " );
3137817466cbSJens Wiklander 
3138817466cbSJens Wiklander     for( i = 0; i < GCD_PAIR_COUNT; i++ )
3139817466cbSJens Wiklander     {
3140817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) );
3141817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) );
3142817466cbSJens Wiklander 
3143817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) );
3144817466cbSJens Wiklander 
3145817466cbSJens Wiklander         if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
3146817466cbSJens Wiklander         {
3147817466cbSJens Wiklander             if( verbose != 0 )
3148817466cbSJens Wiklander                 mbedtls_printf( "failed at %d\n", i );
3149817466cbSJens Wiklander 
3150817466cbSJens Wiklander             ret = 1;
3151817466cbSJens Wiklander             goto cleanup;
3152817466cbSJens Wiklander         }
3153817466cbSJens Wiklander     }
3154817466cbSJens Wiklander 
3155817466cbSJens Wiklander     if( verbose != 0 )
3156817466cbSJens Wiklander         mbedtls_printf( "passed\n" );
3157817466cbSJens Wiklander 
3158817466cbSJens Wiklander cleanup:
3159817466cbSJens Wiklander 
3160817466cbSJens Wiklander     if( ret != 0 && verbose != 0 )
31617901324dSJerome Forissier         mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret );
3162817466cbSJens Wiklander 
3163817466cbSJens Wiklander     mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X );
3164817466cbSJens Wiklander     mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V );
3165817466cbSJens Wiklander 
3166817466cbSJens Wiklander     if( verbose != 0 )
3167817466cbSJens Wiklander         mbedtls_printf( "\n" );
3168817466cbSJens Wiklander 
3169817466cbSJens Wiklander     return( ret );
3170817466cbSJens Wiklander }
3171817466cbSJens Wiklander 
3172817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
3173817466cbSJens Wiklander 
3174817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */
3175