From 0be02bd823c07737775a2251e7426270f2c4f902 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 19 Jul 2021 16:32:54 +0200 Subject: [PATCH] Add accessor functions for cipher_info fields Add functions to read the type, mode, name and key_bitlen fields from mbedtls_cipher_info_t. These are the fields that applications are most likely to care about. TLS code also uses iv_size and block_size, which it might make sense to expose, but most applications shouldn't need those, so I'm not exposing them for now. Call the new functions in unit tests, so they're at least smoke-tested. Signed-off-by: Gilles Peskine --- include/mbedtls/cipher.h | 76 +++++++++++++++++++++++++ tests/suites/test_suite_cipher.function | 42 +++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index 9c9a2e88c..7921f4d85 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -414,6 +414,82 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_ciph int key_bitlen, const mbedtls_cipher_mode_t mode ); +/** + * \brief Retrieve the identifier for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The full cipher identifier (\c MBEDTLS_CIPHER_xxx). + * \return #MBEDTLS_CIPHER_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( MBEDTLS_CIPHER_NONE ); + else + return( info->MBEDTLS_PRIVATE(type) ); +} + +/** + * \brief Retrieve the operation mode for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher mode (\c MBEDTLS_MODE_xxx). + * \return #MBEDTLS_MODE_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( MBEDTLS_MODE_NONE ); + else + return( info->MBEDTLS_PRIVATE(mode) ); +} + +/** + * \brief Retrieve the key size for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The key length in bits. + * For variable-sized ciphers, this is the default length. + * For DES, this includes the parity bits. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_key_bitlen( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); + else + return( info->MBEDTLS_PRIVATE(key_bitlen) ); +} + +/** + * \brief Retrieve the human-readable name for a + * cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher name, which is a human readable string, + * with static storage duration. + * \return \c NULL if \c info is \p NULL. + */ +static inline const char *mbedtls_cipher_info_get_name( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( NULL ); + else + return( info->MBEDTLS_PRIVATE(name) ); +} + /** * \brief This function initializes a \p cipher_context as NONE. * diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index 674349f76..94ea88f79 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -13,6 +13,38 @@ #define MBEDTLS_CIPHER_AUTH_CRYPT #endif +/* Check the internal consistency of a cipher info structure, and + * check it against mbedtls_cipher_info_from_xxx(). */ +static int check_cipher_info( mbedtls_cipher_type_t type, + const mbedtls_cipher_info_t *info ) +{ + size_t key_bitlen; + + TEST_ASSERT( info != NULL ); + TEST_EQUAL( type, mbedtls_cipher_info_get_type( info ) ); + TEST_EQUAL( type, info->type ); + TEST_ASSERT( mbedtls_cipher_info_from_type( type ) == info ); + + TEST_EQUAL( info->mode, mbedtls_cipher_info_get_mode( info ) ); + + /* Insist that get_name() return the string from the structure and + * not a copy. A copy would have an unknown storage duration. */ + TEST_ASSERT( mbedtls_cipher_info_get_name( info ) == info->name ); + TEST_ASSERT( mbedtls_cipher_info_from_string( info->name ) == info ); + + key_bitlen = mbedtls_cipher_info_get_key_bitlen( info ); + TEST_ASSERT( key_bitlen % 8 == 0 ); + /* All current and plausible supported ciphers use a 64-bit, 128-bit + * or 256-bit key, except XTS which uses a double AES key. */ + TEST_ASSERT( key_bitlen >= 64 ); + TEST_ASSERT( key_bitlen <= 512 ); + + return( 1 ); + +exit: + return( 0 ); +} + #if defined(MBEDTLS_CIPHER_AUTH_CRYPT) /* Helper for resetting key/direction * @@ -81,7 +113,13 @@ void mbedtls_cipher_list( ) const int *cipher_type; for( cipher_type = mbedtls_cipher_list(); *cipher_type != 0; cipher_type++ ) - TEST_ASSERT( mbedtls_cipher_info_from_type( *cipher_type ) != NULL ); + { + const mbedtls_cipher_info_t *info = + mbedtls_cipher_info_from_type( *cipher_type ); + mbedtls_test_set_step( *cipher_type ); + if( ! check_cipher_info( *cipher_type, info ) ) + goto exit; + } } /* END_CASE */ @@ -309,6 +347,8 @@ void enc_dec_buf( int cipher_id, char * cipher_string, int key_len, cipher_info = mbedtls_cipher_info_from_type( cipher_id ); TEST_ASSERT( NULL != cipher_info ); TEST_ASSERT( mbedtls_cipher_info_from_string( cipher_string ) == cipher_info ); + TEST_ASSERT( strcmp( mbedtls_cipher_info_get_name( cipher_info ), + cipher_string ) == 0 ); /* Initialise enc and dec contexts */ TEST_ASSERT( 0 == mbedtls_cipher_setup( &ctx_dec, cipher_info ) );