diff options
Diffstat (limited to 'thirdparty/mbedtls/library/bignum.c')
| -rw-r--r-- | thirdparty/mbedtls/library/bignum.c | 192 | 
1 files changed, 143 insertions, 49 deletions
| diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c index 87ccf42fad..2feb727d89 100644 --- a/thirdparty/mbedtls/library/bignum.c +++ b/thirdparty/mbedtls/library/bignum.c @@ -1,8 +1,14 @@  /*   *  Multi-precision integer library   * - *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - *  SPDX-License-Identifier: Apache-2.0 + *  Copyright The Mbed TLS Contributors + *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + *  This file is provided under the Apache License 2.0, or the + *  GNU General Public License v2.0 or later. + * + *  ********** + *  Apache License 2.0:   *   *  Licensed under the Apache License, Version 2.0 (the "License"); you may   *  not use this file except in compliance with the License. @@ -16,7 +22,26 @@   *  See the License for the specific language governing permissions and   *  limitations under the License.   * - *  This file is part of mbed TLS (https://tls.mbed.org) + *  ********** + * + *  ********** + *  GNU General Public License v2.0 or later: + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License along + *  with this program; if not, write to the Free Software Foundation, Inc., + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + *  **********   */  /* @@ -243,6 +268,22 @@ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y )  }  /* + * Conditionally assign dest = src, without leaking information + * about whether the assignment was made or not. + * dest and src must be arrays of limbs of size n. + * assign must be 0 or 1. + */ +static void mpi_safe_cond_assign( size_t n, +                                  mbedtls_mpi_uint *dest, +                                  const mbedtls_mpi_uint *src, +                                  unsigned char assign ) +{ +    size_t i; +    for( i = 0; i < n; i++ ) +        dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign; +} + +/*   * Conditionally assign X = Y, without leaking information   * about whether the assignment was made or not.   * (Leaking information about the respective sizes of X and Y is ok however.) @@ -261,10 +302,9 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned      X->s = X->s * ( 1 - assign ) + Y->s * assign; -    for( i = 0; i < Y->n; i++ ) -        X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; +    mpi_safe_cond_assign( Y->n, X->p, Y->p, assign ); -    for( ; i < X->n; i++ ) +    for( i = Y->n; i < X->n; i++ )          X->p[i] *= ( 1 - assign );  cleanup: @@ -1249,10 +1289,24 @@ cleanup:      return( ret );  } -/* - * Helper for mbedtls_mpi subtraction +/** + * Helper for mbedtls_mpi subtraction. + * + * Calculate d - s where d and s have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise). + * + * \param n             Number of limbs of \p d and \p s. + * \param[in,out] d     On input, the left operand. + *                      On output, the result of the subtraction: + * \param[in] s         The right operand. + * + * \return              1 if `d < s`. + *                      0 if `d >= s`.   */ -static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, +                                     mbedtls_mpi_uint *d, +                                     const mbedtls_mpi_uint *s )  {      size_t i;      mbedtls_mpi_uint c, z; @@ -1263,28 +1317,22 @@ static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )          c = ( *d < *s ) + z; *d -= *s;      } -    while( c != 0 ) -    { -        z = ( *d < c ); *d -= c; -        c = z; d++; -    } +    return( c );  }  /* - * Unsigned subtraction: X = |A| - |B|  (HAC 14.9) + * Unsigned subtraction: X = |A| - |B|  (HAC 14.9, 14.10)   */  int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )  {      mbedtls_mpi TB;      int ret;      size_t n; +    mbedtls_mpi_uint carry;      MPI_VALIDATE_RET( X != NULL );      MPI_VALIDATE_RET( A != NULL );      MPI_VALIDATE_RET( B != NULL ); -    if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) -        return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); -      mbedtls_mpi_init( &TB );      if( X == B ) @@ -1307,7 +1355,21 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi          if( B->p[n - 1] != 0 )              break; -    mpi_sub_hlp( n, B->p, X->p ); +    carry = mpi_sub_hlp( n, X->p, B->p ); +    if( carry != 0 ) +    { +        /* Propagate the carry to the first nonzero limb of X. */ +        for( ; n < X->n && X->p[n] == 0; n++ ) +            --X->p[n]; +        /* If we ran out of space for the carry, it means that the result +         * is negative. */ +        if( n == X->n ) +        { +            ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; +            goto cleanup; +        } +        --X->p[n]; +    }  cleanup: @@ -1887,18 +1949,34 @@ static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )      *mm = ~x + 1;  } -/* - * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36) +/** Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36) + * + * \param[in,out]   A   One of the numbers to multiply. + *                      It must have at least as many limbs as N + *                      (A->n >= N->n), and any limbs beyond n are ignored. + *                      On successful completion, A contains the result of + *                      the multiplication A * B * R^-1 mod N where + *                      R = (2^ciL)^n. + * \param[in]       B   One of the numbers to multiply. + *                      It must be nonzero and must not have more limbs than N + *                      (B->n <= N->n). + * \param[in]       N   The modulo. N must be odd. + * \param           mm  The value calculated by `mpi_montg_init(&mm, N)`. + *                      This is -N^-1 mod 2^ciL. + * \param[in,out]   T   A bignum for temporary storage. + *                      It must be at least twice the limb size of N plus 2 + *                      (T->n >= 2 * (N->n + 1)). + *                      Its initial content is unused and + *                      its final content is indeterminate. + *                      Note that unlike the usual convention in the library + *                      for `const mbedtls_mpi*`, the content of T can change.   */ -static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, +static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm,                           const mbedtls_mpi *T )  {      size_t i, n, m;      mbedtls_mpi_uint u0, u1, *d; -    if( T->n < N->n + 1 || T->p == NULL ) -        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); -      memset( T->p, 0, T->n * ciL );      d = T->p; @@ -1919,22 +1997,34 @@ static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi          *d++ = u0; d[n + 1] = 0;      } -    memcpy( A->p, d, ( n + 1 ) * ciL ); - -    if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) -        mpi_sub_hlp( n, N->p, A->p ); -    else -        /* prevent timing attacks */ -        mpi_sub_hlp( n, A->p, T->p ); - -    return( 0 ); +    /* At this point, d is either the desired result or the desired result +     * plus N. We now potentially subtract N, avoiding leaking whether the +     * subtraction is performed through side channels. */ + +    /* Copy the n least significant limbs of d to A, so that +     * A = d if d < N (recall that N has n limbs). */ +    memcpy( A->p, d, n * ciL ); +    /* If d >= N then we want to set A to d - N. To prevent timing attacks, +     * do the calculation without using conditional tests. */ +    /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ +    d[n] += 1; +    d[n] -= mpi_sub_hlp( n, d, N->p ); +    /* If d0 < N then d < (2^biL)^n +     * so d[n] == 0 and we want to keep A as it is. +     * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n +     * so d[n] == 1 and we want to set A to the result of the subtraction +     * which is d - (2^biL)^n, i.e. the n least significant limbs of d. +     * This exactly corresponds to a conditional assignment. */ +    mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] );  }  /*   * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters.   */ -static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, -                        mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, +                         mbedtls_mpi_uint mm, const mbedtls_mpi *T )  {      mbedtls_mpi_uint z = 1;      mbedtls_mpi U; @@ -1942,7 +2032,7 @@ static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N,      U.n = U.s = (int) z;      U.p = &z; -    return( mpi_montmul( A, &U, N, mm, T ) ); +    mpi_montmul( A, &U, N, mm, T );  }  /* @@ -1957,7 +2047,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,      size_t i, j, nblimbs;      size_t bufsize, nbits;      mbedtls_mpi_uint ei, mm, state; -    mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; +    mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;      int neg;      MPI_VALIDATE_RET( X != NULL ); @@ -1971,6 +2061,10 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,      if( mbedtls_mpi_cmp_int( E, 0 ) < 0 )          return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); +    if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS || +        mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS ) +        return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); +      /*       * Init temps and window size       */ @@ -2028,13 +2122,13 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,      else          MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); -    MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); +    mpi_montmul( &W[1], &RR, N, mm, &T );      /*       * X = R^2 * R^-1 mod N = R mod N       */      MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); -    MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); +    mpi_montred( X, N, mm, &T );      if( wsize > 1 )      { @@ -2047,7 +2141,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,          MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1]    ) );          for( i = 0; i < wsize - 1; i++ ) -            MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); +            mpi_montmul( &W[j], &W[j], N, mm, &T );          /*           * W[i] = W[i - 1] * W[1] @@ -2057,7 +2151,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,              MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) );              MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); -            MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); +            mpi_montmul( &W[i], &W[1], N, mm, &T );          }      } @@ -2094,7 +2188,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,              /*               * out of window, square X               */ -            MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); +            mpi_montmul( X, X, N, mm, &T );              continue;          } @@ -2112,12 +2206,12 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,               * X = X^wsize R^-1 mod N               */              for( i = 0; i < wsize; i++ ) -                MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); +                mpi_montmul( X, X, N, mm, &T );              /*               * X = X * W[wbits] R^-1 mod N               */ -            MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); +            mpi_montmul( X, &W[wbits], N, mm, &T );              state--;              nbits = 0; @@ -2130,18 +2224,18 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,       */      for( i = 0; i < nbits; i++ )      { -        MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); +        mpi_montmul( X, X, N, mm, &T );          wbits <<= 1;          if( ( wbits & ( one << wsize ) ) != 0 ) -            MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); +            mpi_montmul( X, &W[1], N, mm, &T );      }      /*       * X = A^E * R * R^-1 mod N = A^E mod N       */ -    MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); +    mpi_montred( X, N, mm, &T );      if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 )      { @@ -2247,7 +2341,7 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,      MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) );      Xp = (unsigned char*) X->p; -    f_rng( p_rng, Xp + overhead, size ); +    MBEDTLS_MPI_CHK( f_rng( p_rng, Xp + overhead, size ) );      mpi_bigendian_to_host( X->p, limbs ); |