diff options
Diffstat (limited to 'thirdparty/mbedtls/library/dhm.c')
-rw-r--r-- | thirdparty/mbedtls/library/dhm.c | 204 |
1 files changed, 126 insertions, 78 deletions
diff --git a/thirdparty/mbedtls/library/dhm.c b/thirdparty/mbedtls/library/dhm.c index 8255632a99..535b698ce6 100644 --- a/thirdparty/mbedtls/library/dhm.c +++ b/thirdparty/mbedtls/library/dhm.c @@ -1,8 +1,14 @@ /* * Diffie-Hellman-Merkle key exchange * - * 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. + * + * ********** */ /* * The following sources were referenced in the design of this implementation @@ -105,22 +130,21 @@ static int dhm_read_bignum( mbedtls_mpi *X, */ static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) { - mbedtls_mpi L, U; + mbedtls_mpi U; int ret = 0; - mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); + mbedtls_mpi_init( &U ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); - if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 || + if( mbedtls_mpi_cmp_int( param, 2 ) < 0 || mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) { ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } cleanup: - mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); + mbedtls_mpi_free( &U ); return( ret ); } @@ -156,38 +180,54 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, } /* - * Setup and write the ServerKeyExchange parameters + * Pick a random R in the range [2, M-2] for blinding or key generation. */ -int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, - unsigned char *output, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret, count = 0; - size_t n1, n2, n3; - unsigned char *p; - DHM_VALIDATE_RET( ctx != NULL ); - DHM_VALIDATE_RET( output != NULL ); - DHM_VALIDATE_RET( olen != NULL ); - DHM_VALIDATE_RET( f_rng != NULL ); + int ret, count; + size_t m_size = mbedtls_mpi_size( M ); + size_t m_bitlen = mbedtls_mpi_bitlen( M ); + + count = 0; + do + { + if( count++ > 30 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, m_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, ( m_size * 8 ) - m_bitlen ) ); + } + while( dhm_check_range( R, M ) != 0 ); + +cleanup: + return( ret ); +} + +static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + if( x_size < 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - /* - * Generate X as large as possible ( < P ) - */ - do + if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) ) { MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); - - if( count++ > 10 ) + } + else + { + /* Generate X as large as possible ( <= P - 2 ) */ + ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng ); + if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); + if( ret != 0 ) + return( ret ); } - while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); /* * Calculate GX = G^X mod P @@ -198,8 +238,33 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) return( ret ); +cleanup: + return( ret ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t n1, n2, n3; + unsigned char *p; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + ret = dhm_make_common( ctx, x_size, f_rng, p_rng ); + if( ret != 0 ) + goto cleanup; + /* - * export P, G, GX + * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are + * not required". We omit leading zeros for compactness. */ #define DHM_MPI_EXPORT( X, n ) \ do { \ @@ -225,11 +290,9 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, ctx->len = n1; cleanup: - - if( ret != 0 ) + if( ret != 0 && ret > -128 ) return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); - - return( 0 ); + return( ret ); } /* @@ -281,7 +344,7 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret, count = 0; + int ret; DHM_VALIDATE_RET( ctx != NULL ); DHM_VALIDATE_RET( output != NULL ); DHM_VALIDATE_RET( f_rng != NULL ); @@ -289,40 +352,22 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, if( olen < 1 || olen > ctx->len ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - /* - * generate X and calculate GX = G^X mod P - */ - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); - } - while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, - &ctx->P , &ctx->RP ) ); - - if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) - return( ret ); + ret = dhm_make_common( ctx, x_size, f_rng, p_rng ); + if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); + if( ret != 0 ) + goto cleanup; MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); cleanup: - - if( ret != 0 ) + if( ret != 0 && ret > -128 ) return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); - return( 0 ); + return( ret ); } + /* * Use the blinding method and optimisation suggested in section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, @@ -332,7 +377,10 @@ cleanup: static int dhm_update_blinding( mbedtls_dhm_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret, count; + int ret; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); /* * Don't use any blinding the first time a particular X is used, @@ -366,25 +414,24 @@ static int dhm_update_blinding( mbedtls_dhm_context *ctx, * We need to generate blinding values from scratch */ - /* Vi = random( 2, P-1 ) */ - count = 0; - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); + /* Vi = random( 2, P-2 ) */ + MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) ); - if( count++ > 10 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - } - while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); + /* Vf = Vi^-X mod P + * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), + * then elevate to the Xth power. */ + MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); - /* Vf = Vi^-X mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); cleanup: + mbedtls_mpi_free( &R ); + return( ret ); } @@ -431,8 +478,9 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); } + /* Output the secret without any leading zero byte. This is mandatory + * for TLS per RFC 5246 §8.1.2. */ *olen = mbedtls_mpi_size( &ctx->K ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); cleanup: |