diff --git a/Externals/mbedtls/CMakeLists.txt b/Externals/mbedtls/CMakeLists.txt index f5c18c1351..c4979c51ad 100644 --- a/Externals/mbedtls/CMakeLists.txt +++ b/Externals/mbedtls/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}") -if(CMAKE_COMPILER_IS_GNUCC) +if(CMAKE_COMPILER_IS_GNU) # some warnings we want are not available with old GCC versions # note: starting with CMake 2.8 we could use CMAKE_C_COMPILER_VERSION execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion @@ -26,23 +26,35 @@ if(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ") set(CMAKE_C_FLAGS_CHECK "-Werror -Os") set(CMAKE_C_FLAGS_CHECKFULL "${CMAKE_C_FLAGS_CHECK} -Wcast-qual") -endif(CMAKE_COMPILER_IS_GNUCC) +endif(CMAKE_COMPILER_IS_GNU) if(CMAKE_COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -W -Wdeclaration-after-statement -Wwrite-strings -Wpointer-arith -Wimplicit-fallthrough -Wshadow") set(CMAKE_C_FLAGS_RELEASE "-O2") set(CMAKE_C_FLAGS_DEBUG "-O0 -g3") set(CMAKE_C_FLAGS_COVERAGE "-O0 -g3 --coverage") - set(CMAKE_C_FLAGS_ASAN "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover -O3") - set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ") + set(CMAKE_C_FLAGS_ASAN "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3") + set(CMAKE_C_FLAGS_ASANDBG "-Werror -fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls ") set(CMAKE_C_FLAGS_MEMSAN "-Werror -fsanitize=memory -O3") set(CMAKE_C_FLAGS_MEMSANDBG "-Werror -fsanitize=memory -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2") set(CMAKE_C_FLAGS_CHECK "-Werror -Os") endif(CMAKE_COMPILER_IS_CLANG) -if(MSVC) - set(CMAKE_C_FLAGS_CHECK "/WX") -endif(MSVC) +if(CMAKE_COMPILER_IS_IAR) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --warn_about_c_style_casts --warnings_are_errors -Ohz") +endif(CMAKE_COMPILER_IS_IAR) + +if(CMAKE_COMPILER_IS_MSVC) + # Strictest warnings, and treat as errors + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W3") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") +endif(CMAKE_COMPILER_IS_MSVC) + +if(CMAKE_BUILD_TYPE STREQUAL "Coverage") + if(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG) + set(CMAKE_SHARED_LINKER_FLAGS "--coverage") + endif(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG) +endif(CMAKE_BUILD_TYPE STREQUAL "Coverage") if(LIB_INSTALL_DIR) else() diff --git a/Externals/mbedtls/include/CMakeLists.txt b/Externals/mbedtls/include/CMakeLists.txt new file mode 100644 index 0000000000..1b581a54dd --- /dev/null +++ b/Externals/mbedtls/include/CMakeLists.txt @@ -0,0 +1,16 @@ +option(INSTALL_MBEDTLS_HEADERS "Install mbed TLS headers." ON) + +if(INSTALL_MBEDTLS_HEADERS) + + file(GLOB headers "mbedtls/*.h") + + install(FILES ${headers} + DESTINATION include/mbedtls + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + +endif(INSTALL_MBEDTLS_HEADERS) + +# Make config.h available in an out-of-source build. ssl-opt.sh requires it. +if (NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + link_to_source(mbedtls) +endif() diff --git a/Externals/mbedtls/include/mbedtls/aes.h b/Externals/mbedtls/include/mbedtls/aes.h index a36e825a2e..94e7282d36 100644 --- a/Externals/mbedtls/include/mbedtls/aes.h +++ b/Externals/mbedtls/include/mbedtls/aes.h @@ -1,9 +1,26 @@ /** * \file aes.h * - * \brief AES block cipher + * \brief This file contains AES definitions and functions. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,8 +35,9 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_AES_H #define MBEDTLS_AES_H @@ -33,83 +51,210 @@ #include /* padlock.c and aesni.c rely on these values! */ -#define MBEDTLS_AES_ENCRYPT 1 -#define MBEDTLS_AES_DECRYPT 0 +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ +/* Error codes in range 0x0020-0x0022 */ #define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ #define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ -#if !defined(MBEDTLS_AES_ALT) -// Regular implementation -// +/* Error codes in range 0x0021-0x0025 */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ + +/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ + +/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + /** - * \brief AES context structure - * - * \note buf is able to hold 32 extra bytes, which can be used: - * - for alignment purposes if VIA padlock is used, and/or - * - to simplify key expansion in the 256-bit case by - * generating an extra round key + * \brief The AES context-type definition. */ -typedef struct +typedef struct mbedtls_aes_context { - int nr; /*!< number of rounds */ - uint32_t *rk; /*!< AES round keys */ - uint32_t buf[68]; /*!< unaligned data */ + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ } mbedtls_aes_context; +#if defined(MBEDTLS_CIPHER_MODE_XTS) /** - * \brief Initialize AES context + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context +{ + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. * - * \param ctx AES context to be initialized + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. This must not be \c NULL. */ void mbedtls_aes_init( mbedtls_aes_context *ctx ); /** - * \brief Clear AES context + * \brief This function releases and clears the specified AES context. * - * \param ctx AES context to be cleared + * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_free( mbedtls_aes_context *ctx ); +#if defined(MBEDTLS_CIPHER_MODE_XTS) /** - * \brief AES key schedule (encryption) + * \brief This function initializes the specified AES XTS context. * - * \param ctx AES context to be initialized - * \param key encryption key - * \param keybits must be 128, 192 or 256 + * It must be the first API called before using + * the context. * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + * \param ctx The AES XTS context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); /** - * \brief AES key schedule (decryption) + * \brief This function sets the decryption key. * - * \param ctx AES context to be initialized - * \param key decryption key - * \param keybits must be 128, 192 or 256 + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
* - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); +#if defined(MBEDTLS_CIPHER_MODE_XTS) /** - * \brief AES-ECB block encryption/decryption + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
* - * \return 0 if successful + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. + + * \return \c 0 on success. */ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, int mode, @@ -118,26 +263,45 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CBC) /** - * \brief AES-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (\c 16 Bytes). + * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. */ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, int mode, @@ -147,31 +311,89 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, unsigned char *output ); #endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in Bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length Bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length Bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 Bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_CFB) /** - * \brief AES-CFB128 buffer encryption/decryption. + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. * - * \return 0 if successful + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. */ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, int mode, @@ -182,28 +404,40 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, unsigned char *output ); /** - * \brief AES-CFB8 buffer encryption/decryption. + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. * - * \return 0 if successful + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. */ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, int mode, @@ -213,28 +447,137 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, unsigned char *output ); #endif /*MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /** - * \brief AES-CTR buffer encryption/decryption + * \brief This function performs an AES-CTR encryption or decryption + * operation. * - * Warning: You have to keep the maximum use of your counter in mind! + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. * - * \param ctx AES context - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. * - * \return 0 if successful + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * It must point to a valid \c size_t. + * \param nonce_counter The 128-bit nonce and counter. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. */ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, size_t length, @@ -246,50 +589,84 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, #endif /* MBEDTLS_CIPHER_MODE_CTR */ /** - * \brief Internal AES block encryption function - * (Only exposed to allow overriding it, - * see MBEDTLS_AES_ENCRYPT_ALT) + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. * - * \param ctx AES context - * \param input Plaintext block - * \param output Output (ciphertext) block + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. */ -void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); /** - * \brief Internal AES block decryption function - * (Only exposed to allow overriding it, - * see MBEDTLS_AES_DECRYPT_ALT) + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. * - * \param ctx AES context - * \param input Ciphertext block - * \param output Output (plaintext) block + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. */ -void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_AES_ALT */ -#include "aes_alt.h" -#endif /* MBEDTLS_AES_ALT */ - -#ifdef __cplusplus -extern "C" { +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED #endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_encrypt() + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); /** - * \brief Checkup routine + * \brief Deprecated internal AES block decryption function + * without return value. * - * \return 0 if successful, or 1 if the test failed + * \deprecated Superseded by mbedtls_internal_aes_decrypt() + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_aes_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/aesni.h b/Externals/mbedtls/include/mbedtls/aesni.h index b1b7f1cdec..a4ca012f8a 100644 --- a/Externals/mbedtls/include/mbedtls/aesni.h +++ b/Externals/mbedtls/include/mbedtls/aesni.h @@ -3,6 +3,10 @@ * * \brief AES-NI for hardware AES acceleration on some Intel processors * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +27,12 @@ #ifndef MBEDTLS_AESNI_H #define MBEDTLS_AESNI_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "aes.h" #define MBEDTLS_AESNI_AES 0x02000000u @@ -41,7 +51,10 @@ extern "C" { #endif /** - * \brief AES-NI features detection routine + * \brief Internal function to detect the AES-NI feature in CPUs. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param what The feature to detect * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) @@ -51,7 +64,10 @@ extern "C" { int mbedtls_aesni_has_support( unsigned int what ); /** - * \brief AES-NI AES-ECB block en(de)cryption + * \brief Internal AES-NI AES-ECB block encryption and decryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT @@ -61,12 +77,15 @@ int mbedtls_aesni_has_support( unsigned int what ); * \return 0 on success (cannot fail) */ int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); + int mode, + const unsigned char input[16], + unsigned char output[16] ); /** - * \brief GCM multiplication: c = a * b in GF(2^128) + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param c Result * \param a First operand @@ -76,21 +95,29 @@ int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, * elements of GF(2^128) as per the GCM spec. */ void mbedtls_aesni_gcm_mult( unsigned char c[16], - const unsigned char a[16], - const unsigned char b[16] ); + const unsigned char a[16], + const unsigned char b[16] ); /** - * \brief Compute decryption round keys from encryption round keys + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param invkey Round keys for the equivalent inverse cipher * \param fwdkey Original round keys (for encryption) * \param nr Number of rounds (that is, number of round keys minus one) */ void mbedtls_aesni_inverse_key( unsigned char *invkey, - const unsigned char *fwdkey, int nr ); + const unsigned char *fwdkey, + int nr ); /** - * \brief Perform key expansion (for encryption) + * \brief Internal key expansion for encryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param rk Destination buffer where the round keys are written * \param key Encryption key @@ -99,8 +126,8 @@ void mbedtls_aesni_inverse_key( unsigned char *invkey, * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH */ int mbedtls_aesni_setkey_enc( unsigned char *rk, - const unsigned char *key, - size_t bits ); + const unsigned char *key, + size_t bits ); #ifdef __cplusplus } diff --git a/Externals/mbedtls/include/mbedtls/arc4.h b/Externals/mbedtls/include/mbedtls/arc4.h index 5fc5395a8c..fb044d5b7f 100644 --- a/Externals/mbedtls/include/mbedtls/arc4.h +++ b/Externals/mbedtls/include/mbedtls/arc4.h @@ -3,6 +3,10 @@ * * \brief The ARCFOUR stream cipher * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -19,6 +23,7 @@ * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) + * */ #ifndef MBEDTLS_ARC4_H #define MBEDTLS_ARC4_H @@ -31,18 +36,25 @@ #include -#if !defined(MBEDTLS_ARC4_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + /** - * \brief ARC4 context structure + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * */ -typedef struct +typedef struct mbedtls_arc4_context { int x; /*!< permutation index */ int y; /*!< permutation index */ @@ -50,10 +62,19 @@ typedef struct } mbedtls_arc4_context; +#else /* MBEDTLS_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* MBEDTLS_ARC4_ALT */ + /** * \brief Initialize ARC4 context * * \param ctx ARC4 context to be initialized + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * */ void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); @@ -61,6 +82,11 @@ void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); * \brief Clear ARC4 context * * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * */ void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); @@ -70,6 +96,11 @@ void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); * \param ctx ARC4 context to be setup * \param key the secret key * \param keylen length of the key, in bytes + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * */ void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, unsigned int keylen ); @@ -83,29 +114,31 @@ void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, * \param output buffer for the output data * * \return 0 if successful + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * */ int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, unsigned char *output ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_ARC4_ALT */ -#include "arc4_alt.h" -#endif /* MBEDTLS_ARC4_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * */ int mbedtls_arc4_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/aria.h b/Externals/mbedtls/include/mbedtls/aria.h new file mode 100644 index 0000000000..1e8956ed13 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/aria.h @@ -0,0 +1,370 @@ +/** + * \file aria.h + * + * \brief ARIA block cipher + * + * The ARIA algorithm is a symmetric block cipher that can encrypt and + * decrypt information. It is defined by the Korean Agency for + * Technology and Standards (KATS) in KS X 1213:2004 (in + * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) + * and also described by the IETF in RFC 5794. + */ +/* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +#ifndef MBEDTLS_ARIA_H +#define MBEDTLS_ARIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "platform_util.h" + +#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ +#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ + +#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ +#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */ +#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /**< Bad input data. */ + +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */ + +/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used. + */ +#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */ + +/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */ + +#if !defined(MBEDTLS_ARIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ARIA context-type definition. + */ +typedef struct mbedtls_aria_context +{ + unsigned char nr; /*!< The number of rounds (12, 14 or 16) */ + /*! The ARIA round keys. */ + uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; +} +mbedtls_aria_context; + +#else /* MBEDTLS_ARIA_ALT */ +#include "aria_alt.h" +#endif /* MBEDTLS_ARIA_ALT */ + +/** + * \brief This function initializes the specified ARIA context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The ARIA context to initialize. This must not be \c NULL. + */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ); + +/** + * \brief This function releases and clears the specified ARIA context. + * + * \param ctx The ARIA context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized ARIA context. + */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The encryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of \p key in Bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an ARIA single-block encryption or + * decryption operation. + * + * It performs encryption or decryption (depending on whether + * the key was set for encryption on decryption) on the input + * data buffer defined in the \p input parameter. + * + * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or + * mbedtls_aria_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an ARIA-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aria_init(), and either + * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the ARIA block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an ARIA-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data \p input in Bytes. + * \param iv_off The offset in IV (updated after use). + * This must not be larger than 15. + * \param iv The initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an ARIA-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aria_setkey_enc() + * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an ARIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param length The length of the input data \p input in Bytes. + * \param nc_off The offset in Bytes in the current \p stream_block, + * for resuming within the current cipher stream. The + * offset pointer should be \c 0 at the start of a + * stream. This must not be larger than \c 15 Bytes. + * \param nonce_counter The 128-bit nonce and counter. This must point to + * a read/write buffer of length \c 16 bytes. + * \param stream_block The saved stream block for resuming. This must + * point to a read/write buffer of length \c 16 bytes. + * This is overwritten by the function. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aria_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aria.h */ diff --git a/Externals/mbedtls/include/mbedtls/asn1.h b/Externals/mbedtls/include/mbedtls/asn1.h index 082832c87f..96c1c9a8ab 100644 --- a/Externals/mbedtls/include/mbedtls/asn1.h +++ b/Externals/mbedtls/include/mbedtls/asn1.h @@ -2,7 +2,8 @@ * \file asn1.h * * \brief Generic ASN.1 parsing - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -59,7 +60,7 @@ /** * \name DER constants - * These constants comply with DER encoded the ANS1 type tags. + * These constants comply with the DER encoded ASN.1 type tags. * DER encoding uses hexadecimal representation. * An example DER sequence is:\n * - 0x02 -- tag indicating INTEGER @@ -87,6 +88,21 @@ #define MBEDTLS_ASN1_PRIMITIVE 0x00 #define MBEDTLS_ASN1_CONSTRUCTED 0x20 #define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + /* \} name */ /* \} addtogroup asn1_module */ diff --git a/Externals/mbedtls/include/mbedtls/asn1write.h b/Externals/mbedtls/include/mbedtls/asn1write.h index 73ff32b669..360540a002 100644 --- a/Externals/mbedtls/include/mbedtls/asn1write.h +++ b/Externals/mbedtls/include/mbedtls/asn1write.h @@ -2,7 +2,8 @@ * \file asn1write.h * * \brief ASN.1 buffer writing functionality - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,193 +24,280 @@ #ifndef MBEDTLS_ASN1_WRITE_H #define MBEDTLS_ASN1_WRITE_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "asn1.h" -#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ - g += ret; } while( 0 ) +#define MBEDTLS_ASN1_CHK_ADD(g, f) \ + do { \ + if( ( ret = f ) < 0 ) \ + return( ret ); \ + else \ + g += ret; \ + } while( 0 ) #ifdef __cplusplus extern "C" { #endif /** - * \brief Write a length field in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a length field in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param len the length to write + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param len The length value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); - +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, + size_t len ); /** - * \brief Write a ASN.1 tag in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an ASN.1 tag in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param tag the tag to write + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The tag to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, - unsigned char tag ); + unsigned char tag ); /** - * \brief Write raw buffer data - * Note: function works backwards in data buffer + * \brief Write raw buffer data. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The data buffer to write. + * \param size The length of the data buffer. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); + const unsigned char *buf, size_t size ); #if defined(MBEDTLS_BIGNUM_C) /** - * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) + * in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param X the MPI to write + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param X The MPI to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, + const mbedtls_mpi *X ); #endif /* MBEDTLS_BIGNUM_C */ /** - * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data + * in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); /** - * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data + * in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param oid the OID to write - * \param oid_len length of the OID + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID to write. + * \param oid_len The length of the OID. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len ); + const char *oid, size_t oid_len ); /** - * \brief Write an AlgorithmIdentifier sequence in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param oid the OID of the algorithm - * \param oid_len length of the OID - * \param par_len length of parameters, which must be already written. + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID of the algorithm to write. + * \param oid_len The length of the algorithm's OID. + * \param par_len The length of the parameters, which must be already written. * If 0, NULL parameters are added * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - size_t par_len ); +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, + unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); /** - * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value + * in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param boolean 0 or 1 + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param boolean The boolean value to write, either \c 0 or \c 1. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, + int boolean ); /** - * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value + * in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param val the integer value + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); /** - * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a string in ASN.1 format using a specific + * string encoding tag. + + * \note This function works backwards in data buffer. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param text the text to write - * \param text_len length of the text + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The string encoding tag to write, e.g. + * #MBEDTLS_ASN1_UTF8_STRING. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). * - * \return the length written or a negative error code + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ -int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ); +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, + int tag, const char *text, + size_t text_len ); /** - * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a string in ASN.1 format using the PrintableString + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param text the text to write - * \param text_len length of the text + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, + unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a UTF8 string in ASN.1 format using the UTF8String + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the IA5String + * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ); + const char *text, size_t text_len ); /** - * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf the bitstring - * \param bits the total number of bits in the bitstring + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t bits ); + const unsigned char *buf, size_t bits ); /** - * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer + * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) + * and value in ASN.1 format. * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer + * \note This function works backwards in data buffer. * - * \return the length written or a negative error code + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The buffer holding the data to write. + * \param size The length of the data buffer \p buf. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. */ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); + const unsigned char *buf, size_t size ); /** * \brief Create or find a specific named_data entry for writing in a @@ -217,15 +305,16 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, * a new entry is added to the head of the list. * Warning: Destructive behaviour for the val data! * - * \param list Pointer to the location of the head of the list to seek - * through (will be updated in case of a new entry) - * \param oid The OID to look for - * \param oid_len Size of the OID - * \param val Data to store (can be NULL if you want to fill it by hand) - * \param val_len Minimum length of the data buffer needed + * \param list The pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry). + * \param oid The OID to look for. + * \param oid_len The size of the OID. + * \param val The data to store (can be \c NULL if you want to fill + * it by hand). + * \param val_len The minimum length of the data buffer needed. * - * \return NULL if if there was a memory allocation error, or a pointer - * to the new / existing entry. + * \return A pointer to the new / existing entry on success. + * \return \c NULL if if there was a memory allocation error. */ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, const char *oid, size_t oid_len, diff --git a/Externals/mbedtls/include/mbedtls/base64.h b/Externals/mbedtls/include/mbedtls/base64.h index 352c652db9..0d024164c5 100644 --- a/Externals/mbedtls/include/mbedtls/base64.h +++ b/Externals/mbedtls/include/mbedtls/base64.h @@ -2,7 +2,8 @@ * \file base64.h * * \brief RFC 1521 base64 encoding/decoding - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_BASE64_H #define MBEDTLS_BASE64_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include #define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ @@ -74,6 +81,7 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen ); +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * @@ -81,6 +89,8 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, */ int mbedtls_base64_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/bignum.h b/Externals/mbedtls/include/mbedtls/bignum.h index aa51556a57..a54c18e375 100644 --- a/Externals/mbedtls/include/mbedtls/bignum.h +++ b/Externals/mbedtls/include/mbedtls/bignum.h @@ -1,8 +1,9 @@ /** * \file bignum.h * - * \brief Multi-precision integer library - * + * \brief Multi-precision integer library + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -70,7 +71,7 @@ * Maximum size of MPIs allowed in bits and bytes for user-MPIs. * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) * - * Note: Calculations can results temporarily in larger MPIs. So the number + * Note: Calculations can temporarily result in larger MPIs. So the number * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. */ #define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ @@ -103,36 +104,71 @@ /* * Define the base integer type, architecture-wise. * - * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes) - * by defining MBEDTLS_HAVE_INT32 and undefining MBEDTLS_HAVE_ASM + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. */ -#if ( ! defined(MBEDTLS_HAVE_INT32) && \ - defined(_MSC_VER) && defined(_M_AMD64) ) - #define MBEDTLS_HAVE_INT64 - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; -#else - #if ( ! defined(MBEDTLS_HAVE_INT32) && \ - defined(__GNUC__) && ( \ - defined(__amd64__) || defined(__x86_64__) || \ - defined(__ppc64__) || defined(__powerpc64__) || \ - defined(__ia64__) || defined(__alpha__) || \ - (defined(__sparc__) && defined(__arch64__)) || \ - defined(__s390x__) || defined(__mips64) ) ) - #define MBEDTLS_HAVE_INT64 - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - /* mbedtls_t_udbl defined as 128-bit unsigned int */ - typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); - #define MBEDTLS_HAVE_UDBL - #else - #define MBEDTLS_HAVE_INT32 - typedef int32_t mbedtls_mpi_sint; - typedef uint32_t mbedtls_mpi_uint; - typedef uint64_t mbedtls_t_udbl; - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_HAVE_INT32 && __GNUC__ && 64-bit platform */ -#endif /* !MBEDTLS_HAVE_INT32 && _MSC_VER && _M_AMD64 */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ #ifdef __cplusplus extern "C" { @@ -141,7 +177,7 @@ extern "C" { /** * \brief MPI structure */ -typedef struct +typedef struct mbedtls_mpi { int s; /*!< integer sign */ size_t n; /*!< total # of limbs */ @@ -150,90 +186,115 @@ typedef struct mbedtls_mpi; /** - * \brief Initialize one MPI (make internal references valid) - * This just makes it ready to be set or freed, + * \brief Initialize an MPI context. + * + * This makes the MPI ready to be set or freed, * but does not define a value for the MPI. * - * \param X One MPI to initialize. + * \param X The MPI context to initialize. This must not be \c NULL. */ void mbedtls_mpi_init( mbedtls_mpi *X ); /** - * \brief Unallocate one MPI + * \brief This function frees the components of an MPI context. * - * \param X One MPI to unallocate. + * \param X The MPI context to be cleared. This may be \c NULL, + * in which case this function is a no-op. If it is + * not \c NULL, it must point to an initialized MPI. */ void mbedtls_mpi_free( mbedtls_mpi *X ); /** - * \brief Enlarge to the specified number of limbs + * \brief Enlarge an MPI to the specified number of limbs. * - * \param X MPI to grow - * \param nblimbs The target number of limbs + * \note This function does nothing if the MPI is + * already large enough. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \param X The MPI to grow. It must be initialized. + * \param nblimbs The target number of limbs. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); /** - * \brief Resize down, keeping at least the specified number of limbs + * \brief This function resizes an MPI downwards, keeping at least the + * specified number of limbs. * - * \param X MPI to shrink - * \param nblimbs The minimum number of limbs to keep + * If \c X is smaller than \c nblimbs, it is resized up + * instead. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \param X The MPI to shrink. This must point to an initialized MPI. + * \param nblimbs The minimum number of limbs to keep. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); /** - * \brief Copy the contents of Y into X + * \brief Make a copy of an MPI. * - * \param X Destination MPI - * \param Y Source MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param Y The source MPI. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \note The limb-buffer in the destination MPI is enlarged + * if necessary to hold the value in the source MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); /** - * \brief Swap the contents of X and Y + * \brief Swap the contents of two MPIs. * - * \param X First MPI value - * \param Y Second MPI value + * \param X The first MPI. It must be initialized. + * \param Y The second MPI. It must be initialized. */ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); /** - * \brief Safe conditional assignement X = Y if assign is 1 + * \brief Perform a safe conditional copy of MPI which doesn't + * reveal whether the condition was true or not. * - * \param X MPI to conditionally assign to - * \param Y Value to be assigned - * \param assign 1: perform the assignment, 0: keep X's original value - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * \param X The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param Y The MPI to be assigned from. This must point to an + * initialized MPI. + * \param assign The condition deciding whether to perform the + * assignment or not. Possible values: + * * \c 1: Perform the assignment `X = Y`. + * * \c 0: Keep the original value of \p X. * * \note This function is equivalent to - * if( assign ) mbedtls_mpi_copy( X, Y ); + * `if( assign ) mbedtls_mpi_copy( X, Y );` * except that it avoids leaking any information about whether * the assignment was done or not (the above code may leak * information through branch prediction and/or memory access * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); /** - * \brief Safe conditional swap X <-> Y if swap is 1 + * \brief Perform a safe conditional swap which doesn't + * reveal whether the condition was true or not. * - * \param X First mbedtls_mpi value - * \param Y Second mbedtls_mpi value - * \param assign 1: perform the swap, 0: keep X and Y's original values - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * \param X The first MPI. This must be initialized. + * \param Y The second MPI. This must be initialized. + * \param assign The condition deciding whether to perform + * the swap or not. Possible values: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. * * \note This function is equivalent to * if( assign ) mbedtls_mpi_swap( X, Y ); @@ -241,468 +302,649 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned * the assignment was done or not (the above code may leak * information through branch prediction and/or memory access * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + * */ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); /** - * \brief Set value from integer + * \brief Store integer value in MPI. * - * \param X MPI to set - * \param z Value to use + * \param X The MPI to set. This must be initialized. + * \param z The value to use. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); /** - * \brief Get a specific bit from X + * \brief Get a specific bit from an MPI. * - * \param X MPI to use - * \param pos Zero-based index of the bit in X + * \param X The MPI to query. This must be initialized. + * \param pos Zero-based index of the bit to query. * - * \return Either a 0 or a 1 + * \return \c 0 or \c 1 on success, depending on whether bit \c pos + * of \c X is unset or set. + * \return A negative error code on failure. */ int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); /** - * \brief Set a bit of X to a specific value of 0 or 1 + * \brief Modify a specific bit in an MPI. * - * \note Will grow X if necessary to set a bit to 1 in a not yet - * existing limb. Will not grow if bit should be set to 0 + * \note This function will grow the target MPI if necessary to set a + * bit to \c 1 in a not yet existing limb. It will not grow if + * the bit should be set to \c 0. * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * \param val The value to set the bit to (0 or 1) + * \param X The MPI to modify. This must be initialized. + * \param pos Zero-based index of the bit to modify. + * \param val The desired value of bit \c pos: \c 0 or \c 1. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); /** - * \brief Return the number of zero-bits before the least significant - * '1' bit + * \brief Return the number of bits of value \c 0 before the + * least significant bit of value \c 1. * - * Note: Thus also the zero-based index of the least significant '1' bit + * \note This is the same as the zero-based index of + * the least significant bit of value \c 1. * - * \param X MPI to use + * \param X The MPI to query. + * + * \return The number of bits of value \c 0 before the least significant + * bit of value \c 1 in \p X. */ size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); /** * \brief Return the number of bits up to and including the most - * significant '1' bit' + * significant bit of value \c 1. * - * Note: Thus also the one-based index of the most significant '1' bit + * * \note This is same as the one-based index of the most + * significant bit of value \c 1. * - * \param X MPI to use + * \param X The MPI to query. This must point to an initialized MPI. + * + * \return The number of bits up to and including the most + * significant bit of value \c 1. */ size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); /** - * \brief Return the total size in bytes + * \brief Return the total size of an MPI value in bytes. * - * \param X MPI to use + * \param X The MPI to use. This must point to an initialized MPI. + * + * \note The value returned by this function may be less than + * the number of bytes used to store \p X internally. + * This happens if and only if there are trailing bytes + * of value zero. + * + * \return The least number of bytes capable of storing + * the absolute value of \p X. */ size_t mbedtls_mpi_size( const mbedtls_mpi *X ); /** - * \brief Import from an ASCII string + * \brief Import an MPI from an ASCII string. * - * \param X Destination MPI - * \param radix Input numeric base - * \param s Null-terminated string buffer + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the input string. + * \param s Null-terminated string buffer. * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); /** - * \brief Export into an ASCII string + * \brief Export an MPI to an ASCII string. * - * \param X Source MPI - * \param radix Output numeric base - * \param buf Buffer to write the string to - * \param buflen Length of buf - * \param olen Length of the string written, including final NUL byte + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base of the output string. + * \param buf The buffer to write the string to. This must be writable + * buffer of length \p buflen Bytes. + * \param buflen The available size in Bytes of \p buf. + * \param olen The address at which to store the length of the string + * written, including the final \c NULL byte. This must + * not be \c NULL. * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. - * *olen is always updated to reflect the amount - * of data that has (or would have) been written. + * \note You can call this function with `buflen == 0` to obtain the + * minimum required buffer size in `*olen`. * - * \note Call this function with buflen = 0 to obtain the - * minimum required buffer size in *olen. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf + * is too small to hold the value of \p X in the desired base. + * In this case, `*olen` is nonetheless updated to contain the + * size of \p buf required for a successful call. + * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, char *buf, size_t buflen, size_t *olen ); #if defined(MBEDTLS_FS_IO) /** - * \brief Read X from an opened file + * \brief Read an MPI from a line in an opened file. * - * \param X Destination MPI - * \param radix Input numeric base - * \param fin Input file handle + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the string representation used + * in the source line. + * \param fin The input file handle to use. This must not be \c NULL. * - * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if - * the file read buffer is too small or a - * MBEDTLS_ERR_MPI_XXX error code + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns \c 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix \c 16. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer + * is too small. + * \return Another negative error code on failure. */ int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); /** - * \brief Write X into an opened file, or stdout if fout is NULL + * \brief Export an MPI into an opened file. * - * \param p Prefix, can be NULL - * \param X Source MPI - * \param radix Output numeric base - * \param fout Output file handle (can be NULL) + * \param p A string prefix to emit prior to the MPI data. + * For example, this might be a label, or "0x" when + * printing in base \c 16. This may be \c NULL if no prefix + * is needed. + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base to be used in the emitted string. + * \param fout The output file handle. This may be \c NULL, in which case + * the output is written to \c stdout. * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - * - * \note Set fout == NULL to print X on the console. + * \return \c 0 if successful. + * \return A negative error code on failure. */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, + int radix, FILE *fout ); #endif /* MBEDTLS_FS_IO */ /** - * \brief Import X from unsigned binary data, big endian + * \brief Import an MPI from unsigned big endian binary data. * - * \param X Destination MPI - * \param buf Input buffer - * \param buflen Input buffer size + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, + size_t buflen ); /** - * \brief Export X into unsigned binary data, big endian. - * Always fills the whole buffer, which will start with zeros - * if the number is smaller. + * \brief Export an MPI into unsigned big endian binary data + * of fixed size. * - * \param X Source MPI - * \param buf Output buffer - * \param buflen Output buffer size + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, + size_t buflen ); /** - * \brief Left-shift: X <<= count + * \brief Perform a left-shift on an MPI: X <<= count * - * \param X MPI to shift - * \param count Amount to shift + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); /** - * \brief Right-shift: X >>= count + * \brief Perform a right-shift on an MPI: X >>= count * - * \param X MPI to shift - * \param count Amount to shift + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); /** - * \brief Compare unsigned values + * \brief Compare the absolute values of two MPIs. * - * \param X Left-hand MPI - * \param Y Right-hand MPI + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. * - * \return 1 if |X| is greater than |Y|, - * -1 if |X| is lesser than |Y| or - * 0 if |X| is equal to |Y| + * \return \c 1 if `|X|` is greater than `|Y|`. + * \return \c -1 if `|X|` is lesser than `|Y|`. + * \return \c 0 if `|X|` is equal to `|Y|`. */ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); /** - * \brief Compare signed values + * \brief Compare two MPIs. * - * \param X Left-hand MPI - * \param Y Right-hand MPI + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. * - * \return 1 if X is greater than Y, - * -1 if X is lesser than Y or - * 0 if X is equal to Y + * \return \c 1 if \p X is greater than \p Y. + * \return \c -1 if \p X is lesser than \p Y. + * \return \c 0 if \p X is equal to \p Y. */ int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); /** - * \brief Compare signed values + * \brief Compare an MPI with an integer. * - * \param X Left-hand MPI - * \param z The integer value to compare to + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param z The integer value to compare \p X to. * - * \return 1 if X is greater than z, - * -1 if X is lesser than z or - * 0 if X is equal to z + * \return \c 1 if \p X is greater than \p z. + * \return \c -1 if \p X is lesser than \p z. + * \return \c 0 if \p X is equal to \p z. */ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); /** - * \brief Unsigned addition: X = |A| + |B| + * \brief Perform an unsigned addition of MPIs: X = |A| + |B| * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Unsigned subtraction: X = |A| - |B| + * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. + * \return Another negative error code on different kinds of failure. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Signed addition: X = A + B + * \brief Perform a signed addition of MPIs: X = A + B * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Signed subtraction: X = A - B + * \brief Perform a signed subtraction of MPIs: X = A - B * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Signed addition: X = A + b + * \brief Perform a signed addition of an MPI and an integer: X = A + b * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to add + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param b The second summand. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); /** - * \brief Signed subtraction: X = A - b + * \brief Perform a signed subtraction of an MPI and an integer: + * X = A - b * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to subtract + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param b The subtrahend. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); /** - * \brief Baseline multiplication: X = A * B + * \brief Perform a multiplication of two MPIs: X = A * B * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param B The second factor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Baseline multiplication: X = A * b + * \brief Perform a multiplication of an MPI with an unsigned integer: + * X = A * b * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The unsigned integer value to multiply with + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param b The second factor. * - * \note b is unsigned + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_uint b ); /** - * \brief Division by mbedtls_mpi: A = Q * B + R + * \brief Perform a division with remainder of two MPIs: + * A = Q * B + R * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param B The divisor. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 - * - * \note Either Q or R can be NULL. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Division by int: A = Q * b + R + * \brief Perform a division with remainder of an MPI by an integer: + * A = Q * b + R * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param b Integer to divide by + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param b The divisor. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 - * - * \note Either Q or R can be NULL. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); /** - * \brief Modulo: R = A mod B + * \brief Perform a modular reduction. R = A mod B * - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param R The destination MPI for the residue value. + * This must point to an initialized MPI. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPI. + * \param B The base of the modular reduction. + * This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. + * \return Another negative error code on different kinds of failure. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Modulo: r = A mod b + * \brief Perform a modular reduction with respect to an integer. + * r = A mod b * - * \param r Destination mbedtls_mpi_uint - * \param A Left-hand MPI - * \param b Integer to divide by + * \param r The address at which to store the residue. + * This must not be \c NULL. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPi. + * \param b The integer base of the modular reduction. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); /** - * \brief Sliding-window exponentiation: X = A^E mod N + * \brief Perform a sliding-window exponentiation: X = A^E mod N * - * \param X Destination MPI - * \param A Left-hand MPI - * \param E Exponent MPI - * \param N Modular MPI - * \param _RR Speed-up MPI used for recalculations + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The base of the exponentiation. + * This must point to an initialized MPI. + * \param E The exponent MPI. This must point to an initialized MPI. + * \param N The base for the modular reduction. This must point to an + * initialized MPI. + * \param _RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. If it hasn't been used after + * the call to mbedtls_mpi_init(), this function will compute + * the helper value and store it in \p _RR for reuse on + * subsequent calls to this function. Otherwise, the function + * will assume that \p _RR holds the helper value set by a + * previous call to mbedtls_mpi_exp_mod(), and reuse it. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or - * if E is negative + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * \return Another negative error code on different kinds of failures. * - * \note _RR is used to avoid re-computing R*R mod N across - * multiple calls, which speeds up things a bit. It can - * be set to NULL if the extra performance is unneeded. */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ); /** - * \brief Fill an MPI X with size bytes of random + * \brief Fill an MPI with a number of random bytes. * - * \param X Destination MPI - * \param size Size in bytes - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param X The destination MPI. This must point to an initialized MPI. + * \param size The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on failure. + * + * \note The bytes obtained from the RNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. */ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** - * \brief Greatest common divisor: G = gcd(A, B) + * \brief Compute the greatest common divisor: G = gcd(A, B) * - * \param G Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI + * \param G The destination MPI. This must point to an initialized MPI. + * \param A The first operand. This must point to an initialized MPI. + * \param B The second operand. This must point to an initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, + const mbedtls_mpi *B ); /** - * \brief Modular inverse: X = A^-1 mod N + * \brief Compute the modular inverse: X = A^-1 mod N * - * \param X Destination MPI - * \param A Left-hand MPI - * \param N Right-hand MPI + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The MPI to calculate the modular inverse of. This must point + * to an initialized MPI. + * \param N The base of the modular inversion. This must point to an + * initialized MPI. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or nil - MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than + * or equal to one. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse + * with respect to \p N. */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *N ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Perform a Miller-Rabin primality test with error + * probability of 2-80. + * + * \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows + * specifying the number of Miller-Rabin rounds. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use a + * context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ /** - * \brief Miller-Rabin primality test + * \brief Miller-Rabin primality test. * - * \param X MPI to check - * \param f_rng RNG function - * \param p_rng RNG parameter + * \warning If \p X is potentially generated by an adversary, for example + * when validating cryptographic parameters that you didn't + * generate yourself and that are supposed to be prime, then + * \p rounds should be at least the half of the security + * strength of the cryptographic algorithm. On the other hand, + * if \p X is chosen uniformly or non-adversially (as is the + * case when mbedtls_mpi_gen_prime calls this function), then + * \p rounds can be much lower. * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param rounds The number of bases to perform the Miller-Rabin primality + * test for. The probability of returning 0 on a composite is + * at most 2-2*\p rounds. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +/** + * \brief Flags for mbedtls_mpi_gen_prime() + * + * Each of these flags is a constraint on the result X returned by + * mbedtls_mpi_gen_prime(). + */ +typedef enum { + MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ + MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ +} mbedtls_mpi_gen_prime_flag_t; /** - * \brief Prime number generation + * \brief Generate a prime number. * - * \param X Destination MPI - * \param nbits Required size of X in bits - * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) - * \param dh_flag If 1, then (X-1)/2 will be prime too - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param X The destination MPI to store the generated prime in. + * This must point to an initialized MPi. + * \param nbits The required size of the destination MPI in bits. + * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. + * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + * \return \c 0 if successful, in which case \p X holds a + * probably prime number. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between + * \c 3 and #MBEDTLS_MPI_MAX_BITS. */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#if defined(MBEDTLS_SELF_TEST) + /** * \brief Checkup routine * @@ -710,6 +952,8 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, */ int mbedtls_mpi_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/blowfish.h b/Externals/mbedtls/include/mbedtls/blowfish.h index 34626eef48..f01573dcaf 100644 --- a/Externals/mbedtls/include/mbedtls/blowfish.h +++ b/Externals/mbedtls/include/mbedtls/blowfish.h @@ -2,7 +2,8 @@ * \file blowfish.h * * \brief Blowfish block cipher - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -32,6 +33,8 @@ #include #include +#include "platform_util.h" + #define MBEDTLS_BLOWFISH_ENCRYPT 1 #define MBEDTLS_BLOWFISH_DECRYPT 0 #define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 @@ -39,62 +42,87 @@ #define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ #define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ -#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ -#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 /**< Bad input data. */ -#if !defined(MBEDTLS_BLOWFISH_ALT) -// Regular implementation -// +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + /** * \brief Blowfish context structure */ -typedef struct +typedef struct mbedtls_blowfish_context { uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ uint32_t S[4][256]; /*!< key dependent S-boxes */ } mbedtls_blowfish_context; +#else /* MBEDTLS_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + /** - * \brief Initialize Blowfish context + * \brief Initialize a Blowfish context. * - * \param ctx Blowfish context to be initialized + * \param ctx The Blowfish context to be initialized. + * This must not be \c NULL. */ void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); /** - * \brief Clear Blowfish context + * \brief Clear a Blowfish context. * - * \param ctx Blowfish context to be cleared + * \param ctx The Blowfish context to be cleared. + * This may be \c NULL, in which case this function + * returns immediately. If it is not \c NULL, it must + * point to an initialized Blowfish context. */ void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); /** - * \brief Blowfish key schedule + * \brief Perform a Blowfish key schedule operation. * - * \param ctx Blowfish context to be initialized - * \param key encryption key - * \param keybits must be between 32 and 448 bits + * \param ctx The Blowfish context to perform the key schedule on. + * \param key The encryption key. This must be a readable buffer of + * length \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be between + * \c 32 and \c 448 and a multiple of \c 8. * - * \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, unsigned int keybits ); /** - * \brief Blowfish-ECB block encryption/decryption + * \brief Perform a Blowfish-ECB block encryption/decryption operation. * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param input 8-byte input block - * \param output 8-byte output block + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param input The input block. This must be a readable buffer + * of size \c 8 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 8 Bytes. * - * \return 0 if successful + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, int mode, @@ -103,9 +131,7 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CBC) /** - * \brief Blowfish-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (8 bytes) + * \brief Perform a Blowfish-CBC buffer encryption/decryption operation. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following @@ -115,15 +141,22 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, * IV, you should either save it manually or use the cipher * module instead. * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be + * multiple of \c 8. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 8 Bytes. It is updated by this function. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. * - * \return 0 if successful, or - * MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, int mode, @@ -135,7 +168,7 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CFB) /** - * \brief Blowfish CFB buffer encryption/decryption. + * \brief Perform a Blowfish CFB buffer encryption/decryption operation. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following @@ -145,15 +178,25 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, * IV, you should either save it manually or use the cipher * module instead. * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in the initialiation vector. + * The value pointed to must be smaller than \c 8 Bytes. + * It is updated by this function to support the aforementioned + * streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of size \c 8 Bytes. It is updated after use. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. * - * \return 0 if successful + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, int mode, @@ -166,22 +209,67 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CTR) /** - * \brief Blowfish-CTR buffer encryption/decryption + * \brief Perform a Blowfish-CTR buffer encryption/decryption operation. * - * Warning: You have to keep the maximum use of your counter in mind! + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. * - * \param ctx Blowfish context - * \param length The length of the data + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**64 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 4 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 4 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**32 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. + * + * Note that for both stategies, sizes are measured in blocks and + * that a Blowfish block is 8 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data in Bytes. * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 64-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream + * within current cipher stream). The offset pointer + * should be \c 0 at the start of a stream and must be + * smaller than \c 8. It is updated by this function. + * \param nonce_counter The 64-bit nonce and counter. This must point to a + * read/write buffer of length \c 8 Bytes. + * \param stream_block The saved stream-block for resuming. This must point to + * a read/write buffer of length \c 8 Bytes. + * \param input The input data. This must be a readable buffer of + * length \p length Bytes. + * \param output The output data. This must be a writable buffer of + * length \p length Bytes. * - * \return 0 if successful + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, size_t length, @@ -196,8 +284,4 @@ int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, } #endif -#else /* MBEDTLS_BLOWFISH_ALT */ -#include "blowfish_alt.h" -#endif /* MBEDTLS_BLOWFISH_ALT */ - #endif /* blowfish.h */ diff --git a/Externals/mbedtls/include/mbedtls/bn_mul.h b/Externals/mbedtls/include/mbedtls/bn_mul.h index cac3f14577..c33bd8d4ab 100644 --- a/Externals/mbedtls/include/mbedtls/bn_mul.h +++ b/Externals/mbedtls/include/mbedtls/bn_mul.h @@ -1,8 +1,9 @@ /** * \file bn_mul.h * - * \brief Multi-precision integer library - * + * \brief Multi-precision integer library + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -37,6 +38,12 @@ #ifndef MBEDTLS_BN_MUL_H #define MBEDTLS_BN_MUL_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "bignum.h" #if defined(MBEDTLS_HAVE_ASM) @@ -48,7 +55,14 @@ /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(__GNUC__) && \ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) -#if defined(__i386__) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) #define MULADDC_INIT \ asm( \ @@ -141,7 +155,7 @@ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); #else @@ -153,7 +167,7 @@ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); #endif /* SSE2 */ #endif /* i386 */ @@ -162,19 +176,19 @@ #define MULADDC_INIT \ asm( \ - "xorq %%r8, %%r8 \n\t" + "xorq %%r8, %%r8\n" #define MULADDC_CORE \ - "movq (%%rsi), %%rax \n\t" \ - "mulq %%rbx \n\t" \ - "addq $8, %%rsi \n\t" \ - "addq %%rcx, %%rax \n\t" \ - "movq %%r8, %%rcx \n\t" \ - "adcq $0, %%rdx \n\t" \ - "nop \n\t" \ - "addq %%rax, (%%rdi) \n\t" \ - "adcq %%rdx, %%rcx \n\t" \ - "addq $8, %%rdi \n\t" + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" #define MULADDC_STOP \ : "+c" (c), "+D" (d), "+S" (s) \ @@ -520,7 +534,7 @@ "swi r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4" "r5", "r6", "r7", "r8", \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ "r9", "r10", "r11", "r12", "r13" \ ); @@ -557,9 +571,8 @@ #endif /* TriCore */ /* - * gcc -O0 by default uses r7 for the frame pointer, so it complains about our - * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, - * passing that option is not easy when building with yotta. + * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about + * our use of r7 below, unless -fomit-frame-pointer is passed. * * On the other hand, -fomit-frame-pointer is implied by any -Ox options with * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by @@ -629,6 +642,23 @@ "r6", "r7", "r8", "r9", "cc" \ ); +#elif defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr r0, [%0], #4 \n\t" \ + "ldr r1, [%1] \n\t" \ + "umaal r1, %2, %3, r0 \n\t" \ + "str r1, [%1], #4 \n\t" + +#define MULADDC_STOP \ + : "=r" (s), "=r" (d), "=r" (c) \ + : "r" (b), "0" (s), "1" (d), "2" (c) \ + : "r0", "r1", "memory" \ + ); + #else #define MULADDC_INIT \ @@ -726,7 +756,7 @@ "sw $10, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ ); #endif /* MIPS */ diff --git a/Externals/mbedtls/include/mbedtls/camellia.h b/Externals/mbedtls/include/mbedtls/camellia.h index 0424d623fb..3eeb66366d 100644 --- a/Externals/mbedtls/include/mbedtls/camellia.h +++ b/Externals/mbedtls/include/mbedtls/camellia.h @@ -2,7 +2,8 @@ * \file camellia.h * * \brief Camellia block cipher - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -32,77 +33,107 @@ #include #include +#include "platform_util.h" + #define MBEDTLS_CAMELLIA_ENCRYPT 1 #define MBEDTLS_CAMELLIA_DECRYPT 0 -#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ -#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /**< Bad input data. */ -#if !defined(MBEDTLS_CAMELLIA_ALT) -// Regular implementation -// +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + /** * \brief CAMELLIA context structure */ -typedef struct +typedef struct mbedtls_camellia_context { int nr; /*!< number of rounds */ uint32_t rk[68]; /*!< CAMELLIA round keys */ } mbedtls_camellia_context; +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + /** - * \brief Initialize CAMELLIA context + * \brief Initialize a CAMELLIA context. * - * \param ctx CAMELLIA context to be initialized + * \param ctx The CAMELLIA context to be initialized. + * This must not be \c NULL. */ void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); /** - * \brief Clear CAMELLIA context + * \brief Clear a CAMELLIA context. * - * \param ctx CAMELLIA context to be cleared + * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, + * in which case this function returns immediately. If it is not + * \c NULL, it must be initialized. */ void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); /** - * \brief CAMELLIA key schedule (encryption) + * \brief Perform a CAMELLIA key schedule operation for encryption. * - * \param ctx CAMELLIA context to be initialized - * \param key encryption key - * \param keybits must be 128, 192 or 256 + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The encryption key to use. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. * - * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ -int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ); +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); /** - * \brief CAMELLIA key schedule (decryption) + * \brief Perform a CAMELLIA key schedule operation for decryption. * - * \param ctx CAMELLIA context to be initialized - * \param key decryption key - * \param keybits must be 128, 192 or 256 + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. * - * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ -int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ); +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); /** - * \brief CAMELLIA-ECB block encryption/decryption + * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param input The input block. This must be a readable buffer + * of size \c 16 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 16 Bytes. * - * \return 0 if successful + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, int mode, @@ -111,9 +142,7 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CBC) /** - * \brief CAMELLIA-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) + * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following @@ -123,15 +152,22 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, * IV, you should either save it manually or use the cipher * module instead. * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length in Bytes of the input data \p input. + * This must be a multiple of \c 16 Bytes. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated to allow streaming + * use as explained above. + * \param input The buffer holding the input data. This must point to a + * readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must point to a + * writable buffer of length \p length Bytes. * - * \return 0 if successful, or - * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, int mode, @@ -143,11 +179,14 @@ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CFB) /** - * \brief CAMELLIA-CFB128 buffer encryption/decryption + * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption + * operation. * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. + * \note Due to the nature of CFB mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following @@ -157,16 +196,24 @@ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, * IV, you should either save it manually or use the cipher * module instead. * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length of the input data \p input. Any value is allowed. + * \param iv_off The current offset in the IV. This must be smaller + * than \c 16 Bytes. It is updated after this call to allow + * the aforementioned streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated after this call to + * allow the aforementioned streaming usage. + * \param input The buffer holding the input data. This must be a readable + * buffer of size \p length Bytes. + * \param output The buffer to hold the output data. This must be a writable + * buffer of length \p length Bytes. * - * \return 0 if successful, or - * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, int mode, @@ -179,26 +226,78 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, #if defined(MBEDTLS_CIPHER_MODE_CTR) /** - * \brief CAMELLIA-CTR buffer encryption/decryption + * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. * - * Warning: You have to keep the maximum use of your counter in mind! + * *note Due to the nature of CTR mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. * - * \param ctx CAMELLIA context - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first \c 12 Bytes for the + * per-message nonce, and the last \c 4 Bytes for internal use. + * In that case, before calling this function on a new message you + * need to set the first \c 12 Bytes of \p nonce_counter to your + * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 + * (which will cause \p stream_block to be ignored). That way, you + * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks + * each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be + * unique. The recommended way to ensure uniqueness is to use a + * message counter. An alternative is to generate random nonces, + * but this limits the number of messages that can be securely + * encrypted: for example, with 96-bit random nonces, you should + * not encrypt more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that a CAMELLIA block is \c 16 Bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data \p input in Bytes. + * Any value is allowed. + * \param nc_off The offset in the current \p stream_block (for resuming * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream + * should be \c 0 at the start of a stream. It is updated + * at the end of this call. + * \param nonce_counter The 128-bit nonce and counter. This must be a read/write + * buffer of length \c 16 Bytes. + * \param stream_block The saved stream-block for resuming. This must be a + * read/write buffer of length \c 16 Bytes. + * \param input The input data stream. This must be a readable buffer of + * size \p length Bytes. + * \param output The output data stream. This must be a writable buffer + * of size \p length Bytes. * - * \return 0 if successful + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, size_t length, @@ -209,17 +308,7 @@ int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, unsigned char *output ); #endif /* MBEDTLS_CIPHER_MODE_CTR */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_CAMELLIA_ALT */ -#include "camellia_alt.h" -#endif /* MBEDTLS_CAMELLIA_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine @@ -228,6 +317,8 @@ extern "C" { */ int mbedtls_camellia_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/ccm.h b/Externals/mbedtls/include/mbedtls/ccm.h index ef75839baa..f03e3b580e 100644 --- a/Externals/mbedtls/include/mbedtls/ccm.h +++ b/Externals/mbedtls/include/mbedtls/ccm.h @@ -1,9 +1,34 @@ /** * \file ccm.h * - * \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers + * \brief This file provides an API for the CCM authenticated encryption + * mode for block ciphers. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,46 +43,69 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_CCM_H #define MBEDTLS_CCM_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "cipher.h" -#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + /** - * \brief CCM context structure + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. */ -typedef struct { - mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ +typedef struct mbedtls_ccm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ } mbedtls_ccm_context; +#else /* MBEDTLS_CCM_ALT */ +#include "ccm_alt.h" +#endif /* MBEDTLS_CCM_ALT */ + /** - * \brief Initialize CCM context (just makes references valid) - * Makes the context ready for mbedtls_ccm_setkey() or - * mbedtls_ccm_free(). + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). * - * \param ctx CCM context to initialize + * \param ctx The CCM context to initialize. This must not be \c NULL. */ void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); /** - * \brief CCM initialization (encryption and decryption) + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. * - * \param ctx CCM context to be initialized - * \param cipher cipher to use (a 128-bit block cipher) - * \param key encryption key - * \param keybits key size in bits (must be acceptable by the cipher) + * \param ctx The CCM context to initialize. This must be an initialized + * context. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must not be \c NULL. + * \param keybits The key size in bits. This must be acceptable by the cipher. * - * \return 0 if successful, or a cipher specific error code + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, mbedtls_cipher_id_t cipher, @@ -65,36 +113,49 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, unsigned int keybits ); /** - * \brief Free a CCM context and underlying cipher sub-context + * \brief This function releases and clears the specified CCM context + * and underlying cipher sub-context. * - * \param ctx CCM context to free + * \param ctx The CCM context to clear. If this is \c NULL, the function + * has no effect. Otherwise, this must be initialized. */ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); /** - * \brief CCM buffer encryption + * \brief This function encrypts a buffer using CCM. * - * \param ctx CCM context - * \param length length of the input data in bytes - * \param iv nonce (initialization vector) - * \param iv_len length of IV in bytes - * must be 2, 3, 4, 5, 6, 7 or 8 - * \param add additional data - * \param add_len length of additional data in bytes - * must be less than 2^16 - 2^8 - * \param input buffer holding the input data - * \param output buffer for holding the output data - * must be at least 'length' bytes wide - * \param tag buffer for holding the tag - * \param tag_len length of the tag to generate in bytes - * must be 4, 6, 8, 10, 14 or 16 + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. * - * \note The tag is written to a separate buffer. To get the tag - * concatenated with the output as in the CCM spec, use - * tag = output + length and make sure the output buffer is - * at least length + tag_len wide. + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. If \p add_len is greater than + * zero, \p add must be a readable buffer of at least that + * length. + * \param add_len The length of additional data in Bytes. + * This must be less than `2^16 - 2^8`. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. * - * \return 0 if successful + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, @@ -103,21 +164,83 @@ int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, unsigned char *tag, size_t tag_len ); /** - * \brief CCM buffer authenticated decryption + * \brief This function encrypts a buffer using CCM*. * - * \param ctx CCM context - * \param length length of the input data - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data - * \param add_len length of additional data - * \param input buffer holding the input data - * \param output buffer for holding the output data - * \param tag buffer holding the tag - * \param tag_len length of the tag + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. * - * \return 0 if successful and authenticated, - * MBEDTLS_ERR_CCM_AUTH_FAILED if tag does not match + * \note When using this function in a variable tag length context, + * the tag length has to be encoded into the \p iv passed to + * this function. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer + * of at least that \p add_len Bytes.. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. This indicates that the message is authentic. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. */ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, @@ -125,11 +248,57 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len ); +/** + * \brief This function performs a CCM* authenticated decryption of a + * buffer. + * + * \note When using this function in a variable tag length context, + * the tag length has to be decoded from \p iv and passed to + * this function as \p tag_len. (\p tag needs to be adjusted + * accordingly.) + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least that \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field in Bytes. + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is nos + * longer authenticated. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /** - * \brief Checkup routine + * \brief The CCM checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_ccm_self_test( int verbose ); #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ diff --git a/Externals/mbedtls/include/mbedtls/certs.h b/Externals/mbedtls/include/mbedtls/certs.h index ca49086e4f..b7c5708f85 100644 --- a/Externals/mbedtls/include/mbedtls/certs.h +++ b/Externals/mbedtls/include/mbedtls/certs.h @@ -2,7 +2,8 @@ * \file certs.h * * \brief Sample certificates and DHM parameters for testing - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_CERTS_H #define MBEDTLS_CERTS_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include #ifdef __cplusplus diff --git a/Externals/mbedtls/include/mbedtls/chacha20.h b/Externals/mbedtls/include/mbedtls/chacha20.h new file mode 100644 index 0000000000..2ae5e6e5f4 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/chacha20.h @@ -0,0 +1,226 @@ +/** + * \file chacha20.h + * + * \brief This file contains ChaCha20 definitions and functions. + * + * ChaCha20 is a stream cipher that can encrypt and decrypt + * information. ChaCha was created by Daniel Bernstein as a variant of + * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf + * ChaCha20 is the variant with 20 rounds, that was also standardized + * in RFC 7539. + * + * \author Daniel King + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +#ifndef MBEDTLS_CHACHA20_H +#define MBEDTLS_CHACHA20_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct mbedtls_chacha20_context +{ + uint32_t state[16]; /*! The state (before round operations). */ + uint8_t keystream8[64]; /*! Leftover keystream bytes. */ + size_t keystream_bytes_used; /*! Number of keystream bytes already used. */ +} +mbedtls_chacha20_context; + +#else /* MBEDTLS_CHACHA20_ALT */ +#include "chacha20_alt.h" +#endif /* MBEDTLS_CHACHA20_ALT */ + +/** + * \brief This function initializes the specified ChaCha20 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by calls to + * \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts(), then one or more calls to + * to \c mbedtls_chacha20_update(), and finally to + * \c mbedtls_chacha20_free(). + * + * \param ctx The ChaCha20 context to initialize. + * This must not be \c NULL. + */ +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. This may be \c NULL, + * in which case this function is a no-op. If it is not + * \c NULL, it must point to an initialized context. + * + */ +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function sets the encryption/decryption key. + * + * \note After using this function, you must also call + * \c mbedtls_chacha20_starts() to set a nonce before you + * start encrypting/decrypting data with + * \c mbedtls_chacha_update(). + * + * \param ctx The ChaCha20 context to which the key should be bound. + * It must be initialized. + * \param key The encryption/decryption key. This must be \c 32 Bytes + * in length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. + */ +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function sets the nonce and initial counter value. + * + * \note A ChaCha20 context can be re-used with the same key by + * calling this function to change the nonce. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality guarantees for the + * messages encrypted with the same nonce and key. + * + * \param ctx The ChaCha20 context to which the nonce should be bound. + * It must be initialized and bound to a key. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is + * NULL. + */ +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ); + +/** + * \brief This function encrypts or decrypts data. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \note \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts() must be called at least once + * to setup the context before this function can be called. + * + * \note This function can be called multiple times in a row in + * order to encrypt of decrypt data piecewise with the same + * key and nonce. + * + * \param ctx The ChaCha20 context to use for encryption or decryption. + * It must be initialized and bound to a key and nonce. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function encrypts or decrypts data with ChaCha20 and + * the given key and nonce. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \warning You must never use the same (key, nonce) pair more than + * once. This would void any confidentiality guarantees for + * the messages encrypted with the same nonce and key. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \param key The encryption/decryption key. + * This must be \c 32 Bytes in length. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t size, + const unsigned char* input, + unsigned char* output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chacha20_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHA20_H */ diff --git a/Externals/mbedtls/include/mbedtls/chachapoly.h b/Externals/mbedtls/include/mbedtls/chachapoly.h new file mode 100644 index 0000000000..49e615d278 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/chachapoly.h @@ -0,0 +1,358 @@ +/** + * \file chachapoly.h + * + * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and + * functions. + * + * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption + * with Associated Data (AEAD) that can be used to encrypt and + * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel + * Bernstein and was standardized in RFC 7539. + * + * \author Daniel King + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +#ifndef MBEDTLS_CHACHAPOLY_H +#define MBEDTLS_CHACHAPOLY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* for shared error codes */ +#include "poly1305.h" + +#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */ +#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ + MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ +} +mbedtls_chachapoly_mode_t; + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#include "chacha20.h" + +typedef struct mbedtls_chachapoly_context +{ + mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ + mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ + uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */ + int state; /**< The current state of the context. */ + mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */ +} +mbedtls_chachapoly_context; + +#else /* !MBEDTLS_CHACHAPOLY_ALT */ +#include "chachapoly_alt.h" +#endif /* !MBEDTLS_CHACHAPOLY_ALT */ + +/** + * \brief This function initializes the specified ChaCha20-Poly1305 context. + * + * It must be the first API called before using + * the context. It must be followed by a call to + * \c mbedtls_chachapoly_setkey() before any operation can be + * done, and to \c mbedtls_chachapoly_free() once all + * operations with that context have been finished. + * + * In order to encrypt or decrypt full messages at once, for + * each message you should make a single call to + * \c mbedtls_chachapoly_crypt_and_tag() or + * \c mbedtls_chachapoly_auth_decrypt(). + * + * In order to encrypt messages piecewise, for each + * message you should make a call to + * \c mbedtls_chachapoly_starts(), then 0 or more calls to + * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to + * \c mbedtls_chachapoly_update(), then one call to + * \c mbedtls_chachapoly_finish(). + * + * \warning Decryption with the piecewise API is discouraged! Always + * use \c mbedtls_chachapoly_auth_decrypt() when possible! + * + * If however this is not possible because the data is too + * large to fit in memory, you need to: + * + * - call \c mbedtls_chachapoly_starts() and (if needed) + * \c mbedtls_chachapoly_update_aad() as above, + * - call \c mbedtls_chachapoly_update() multiple times and + * ensure its output (the plaintext) is NOT used in any other + * way than placing it in temporary storage at this point, + * - call \c mbedtls_chachapoly_finish() to compute the + * authentication tag and compared it in constant time to the + * tag received with the ciphertext. + * + * If the tags are not equal, you must immediately discard + * all previous outputs of \c mbedtls_chachapoly_update(), + * otherwise you can now safely use the plaintext. + * + * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. + */ +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20-Poly1305 context. + * + * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which + * case this function is a no-op. + */ +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function sets the ChaCha20-Poly1305 + * symmetric encryption key. + * + * \param ctx The ChaCha20-Poly1305 context to which the key should be + * bound. This must be initialized. + * \param key The \c 256 Bit (\c 32 Bytes) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function starts a ChaCha20-Poly1305 encryption or + * decryption operation. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \note If the context is being used for AAD only (no data to + * encrypt or decrypt) then \p mode can be set to any value. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param nonce The nonce/IV to use for the message. + * This must be a redable buffer of length \c 12 Bytes. + * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or + * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ); + +/** + * \brief This function feeds additional data to be authenticated + * into an ongoing ChaCha20-Poly1305 operation. + * + * The Additional Authenticated Data (AAD), also called + * Associated Data (AD) is only authenticated but not + * encrypted nor included in the encrypted output. It is + * usually transmitted separately from the ciphertext or + * computed locally by each party. + * + * \note This function is called before data is encrypted/decrypted. + * I.e. call this function to process the AAD before calling + * \c mbedtls_chachapoly_update(). + * + * You may call this function multiple times to process + * an arbitrary amount of AAD. It is permitted to call + * this function 0 times, if no AAD is used. + * + * This function cannot be called any more if data has + * been processed by \c mbedtls_chachapoly_update(), + * or if the context has been finished. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param aad_len The length in Bytes of the AAD. The length has no + * restrictions. + * \param aad Buffer containing the AAD. + * This pointer can be \c NULL if `aad_len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p aad are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operations has not been started or has been + * finished, or if the AAD has been finished. + */ +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief Thus function feeds data to be encrypted or decrypted + * into an on-going ChaCha20-Poly1305 + * operation. + * + * The direction (encryption or decryption) depends on the + * mode that was given when calling + * \c mbedtls_chachapoly_starts(). + * + * You may call this function multiple times to process + * an arbitrary amount of data. It is permitted to call + * this function 0 times, if no data is to be encrypted + * or decrypted. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param len The length (in bytes) of the data to encrypt or decrypt. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `len == 0`. + * \param output The buffer to where the encrypted or decrypted data is + * written. This must be able to hold \p len bytes. + * This pointer can be \c NULL if `len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finished the ChaCha20-Poly1305 operation and + * generates the MAC (authentication tag). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated encryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * This must be initialized. + * \param length The length (in bytes) of the data to encrypt or decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated + * data (AAD). This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the encrypted or decrypted data + * is written. This pointer can be \c NULL if `ilen == 0`. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC + * is written. This must not be \c NULL. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated decryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in Bytes) of the data to decrypt. + * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param tag The buffer holding the authentication tag. + * This must be a readable buffer of length \c 16 Bytes. + * \param input The buffer containing the data to decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the decrypted data is written. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED + * if the data was not authentic. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20-Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chachapoly_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHAPOLY_H */ diff --git a/Externals/mbedtls/include/mbedtls/check_config.h b/Externals/mbedtls/include/mbedtls/check_config.h index fe86c1e8d1..b86e5807e0 100644 --- a/Externals/mbedtls/include/mbedtls/check_config.h +++ b/Externals/mbedtls/include/mbedtls/check_config.h @@ -2,8 +2,9 @@ * \file check_config.h * * \brief Consistency checks for configuration options - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -77,11 +78,20 @@ #error "MBEDTLS_DHM_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_CMAC_C) && \ !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) #error "MBEDTLS_CMAC_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECDH_C defined, but not all prerequisites" #endif @@ -98,6 +108,17 @@ #error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ + defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ + defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ + defined(MBEDTLS_ECP_INTERNAL_ALT) || \ + defined(MBEDTLS_ECP_ALT) ) +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation" +#endif + #if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #endif @@ -117,6 +138,10 @@ #error "MBEDTLS_ECP_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#endif + #if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ !defined(MBEDTLS_SHA256_C)) #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" @@ -150,10 +175,46 @@ #error "MBEDTLS_GCM_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) #error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) #error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" #endif @@ -618,6 +679,15 @@ #error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + /* * Avoid warning from -pedantic. This is a convenient place for this * workaround since this is included by every single file before the diff --git a/Externals/mbedtls/include/mbedtls/cipher.h b/Externals/mbedtls/include/mbedtls/cipher.h index b12e38843a..082a691741 100644 --- a/Externals/mbedtls/include/mbedtls/cipher.h +++ b/Externals/mbedtls/include/mbedtls/cipher.h @@ -1,11 +1,14 @@ /** * \file cipher.h * - * \brief Generic cipher wrapper. + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. * * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -20,7 +23,7 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CIPHER_H @@ -33,8 +36,9 @@ #endif #include +#include "platform_util.h" -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #define MBEDTLS_CIPHER_MODE_AEAD #endif @@ -42,7 +46,8 @@ #define MBEDTLS_CIPHER_MODE_WITH_PADDING #endif -#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) #define MBEDTLS_CIPHER_MODE_STREAM #endif @@ -51,104 +56,153 @@ #define inline __inline #endif -#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ -#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ -#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ -#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ -#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ -#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid, eg because it was free()ed. */ +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ -#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */ -#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */ +/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ #ifdef __cplusplus extern "C" { #endif +/** + * \brief Supported cipher types. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ typedef enum { - MBEDTLS_CIPHER_ID_NONE = 0, - MBEDTLS_CIPHER_ID_NULL, - MBEDTLS_CIPHER_ID_AES, - MBEDTLS_CIPHER_ID_DES, - MBEDTLS_CIPHER_ID_3DES, - MBEDTLS_CIPHER_ID_CAMELLIA, - MBEDTLS_CIPHER_ID_BLOWFISH, - MBEDTLS_CIPHER_ID_ARC4, + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ + MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ } mbedtls_cipher_id_t; +/** + * \brief Supported {cipher type, cipher mode} pairs. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ typedef enum { - MBEDTLS_CIPHER_NONE = 0, - MBEDTLS_CIPHER_NULL, - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_CIPHER_AES_128_CBC, - MBEDTLS_CIPHER_AES_192_CBC, - MBEDTLS_CIPHER_AES_256_CBC, - MBEDTLS_CIPHER_AES_128_CFB128, - MBEDTLS_CIPHER_AES_192_CFB128, - MBEDTLS_CIPHER_AES_256_CFB128, - MBEDTLS_CIPHER_AES_128_CTR, - MBEDTLS_CIPHER_AES_192_CTR, - MBEDTLS_CIPHER_AES_256_CTR, - MBEDTLS_CIPHER_AES_128_GCM, - MBEDTLS_CIPHER_AES_192_GCM, - MBEDTLS_CIPHER_AES_256_GCM, - MBEDTLS_CIPHER_CAMELLIA_128_ECB, - MBEDTLS_CIPHER_CAMELLIA_192_ECB, - MBEDTLS_CIPHER_CAMELLIA_256_ECB, - MBEDTLS_CIPHER_CAMELLIA_128_CBC, - MBEDTLS_CIPHER_CAMELLIA_192_CBC, - MBEDTLS_CIPHER_CAMELLIA_256_CBC, - MBEDTLS_CIPHER_CAMELLIA_128_CFB128, - MBEDTLS_CIPHER_CAMELLIA_192_CFB128, - MBEDTLS_CIPHER_CAMELLIA_256_CFB128, - MBEDTLS_CIPHER_CAMELLIA_128_CTR, - MBEDTLS_CIPHER_CAMELLIA_192_CTR, - MBEDTLS_CIPHER_CAMELLIA_256_CTR, - MBEDTLS_CIPHER_CAMELLIA_128_GCM, - MBEDTLS_CIPHER_CAMELLIA_192_GCM, - MBEDTLS_CIPHER_CAMELLIA_256_GCM, - MBEDTLS_CIPHER_DES_ECB, - MBEDTLS_CIPHER_DES_CBC, - MBEDTLS_CIPHER_DES_EDE_ECB, - MBEDTLS_CIPHER_DES_EDE_CBC, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_CIPHER_DES_EDE3_CBC, - MBEDTLS_CIPHER_BLOWFISH_ECB, - MBEDTLS_CIPHER_BLOWFISH_CBC, - MBEDTLS_CIPHER_BLOWFISH_CFB64, - MBEDTLS_CIPHER_BLOWFISH_CTR, - MBEDTLS_CIPHER_ARC4_128, - MBEDTLS_CIPHER_AES_128_CCM, - MBEDTLS_CIPHER_AES_192_CCM, - MBEDTLS_CIPHER_AES_256_CCM, - MBEDTLS_CIPHER_CAMELLIA_128_CCM, - MBEDTLS_CIPHER_CAMELLIA_192_CCM, - MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ + MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ + MBEDTLS_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */ + MBEDTLS_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ } mbedtls_cipher_type_t; +/** Supported cipher modes. */ typedef enum { - MBEDTLS_MODE_NONE = 0, - MBEDTLS_MODE_ECB, - MBEDTLS_MODE_CBC, - MBEDTLS_MODE_CFB, - MBEDTLS_MODE_OFB, /* Unused! */ - MBEDTLS_MODE_CTR, - MBEDTLS_MODE_GCM, - MBEDTLS_MODE_STREAM, - MBEDTLS_MODE_CCM, + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ } mbedtls_cipher_mode_t; +/** Supported cipher padding types. */ typedef enum { - MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default) */ - MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding */ - MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding */ - MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible!) */ - MBEDTLS_PADDING_NONE, /**< never pad (full blocks only) */ + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ } mbedtls_cipher_padding_t; +/** Type of operation. */ typedef enum { MBEDTLS_OPERATION_NONE = -1, MBEDTLS_DECRYPT = 0, @@ -156,19 +210,19 @@ typedef enum { } mbedtls_operation_t; enum { - /** Undefined key length */ + /** Undefined key length. */ MBEDTLS_KEY_LENGTH_NONE = 0, - /** Key length, in bits (including parity), for DES keys */ + /** Key length, in bits (including parity), for DES keys. */ MBEDTLS_KEY_LENGTH_DES = 64, - /** Key length, in bits (including parity), for DES in two key EDE */ + /** Key length in bits, including parity, for DES in two-key EDE. */ MBEDTLS_KEY_LENGTH_DES_EDE = 128, - /** Key length, in bits (including parity), for DES in three-key EDE */ + /** Key length in bits, including parity, for DES in three-key EDE. */ MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, }; -/** Maximum length of any IV, in bytes */ +/** Maximum length of any IV, in Bytes. */ #define MBEDTLS_MAX_IV_LENGTH 16 -/** Maximum block size of any cipher, in bytes */ +/** Maximum block size of any cipher, in Bytes. */ #define MBEDTLS_MAX_BLOCK_LENGTH 16 /** @@ -182,33 +236,44 @@ typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; /** - * Cipher information. Allows cipher functions to be called in a generic way. + * Cipher information. Allows calling cipher functions + * in a generic way. */ -typedef struct { - /** Full cipher identifier (e.g. MBEDTLS_CIPHER_AES_256_CBC) */ +typedef struct mbedtls_cipher_info_t +{ + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ mbedtls_cipher_type_t type; - /** Cipher mode (e.g. MBEDTLS_MODE_CBC) */ + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ mbedtls_cipher_mode_t mode; - /** Cipher key length, in bits (default length for variable sized ciphers) - * (Includes parity bits for ciphers like DES) */ + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ unsigned int key_bitlen; - /** Name of the cipher */ + /** Name of the cipher. */ const char * name; - /** IV/NONCE size, in bytes. - * For cipher that accept many sizes: recommended size */ + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ unsigned int iv_size; - /** Flags for variable IV size, variable key size, etc. */ + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ int flags; - /** block size, in bytes */ + /** The block size, in Bytes. */ unsigned int block_size; - /** Base cipher information and functions */ + /** Struct for base cipher information and functions. */ const mbedtls_cipher_base_t *base; } mbedtls_cipher_info_t; @@ -216,164 +281,193 @@ typedef struct { /** * Generic cipher context. */ -typedef struct { - /** Information about the associated cipher */ +typedef struct mbedtls_cipher_context_t +{ + /** Information about the associated cipher. */ const mbedtls_cipher_info_t *cipher_info; - /** Key length to use */ + /** Key length to use. */ int key_bitlen; - /** Operation that the context's key has been initialised for */ + /** Operation that the key of the context has been + * initialized for. + */ mbedtls_operation_t operation; #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /** Padding functions to use, if relevant for cipher mode */ + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); #endif - /** Buffer for data that hasn't been encrypted yet */ + /** Buffer for input that has not been processed yet. */ unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; - /** Number of bytes that still need processing */ + /** Number of Bytes that have not been processed yet. */ size_t unprocessed_len; - /** Current IV or NONCE_COUNTER for CTR-mode */ + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; - /** IV size in bytes (for ciphers with variable-length IVs) */ + /** IV size in Bytes, for ciphers with variable-length IVs. */ size_t iv_size; - /** Cipher-specific context */ + /** The cipher-specific context. */ void *cipher_ctx; #if defined(MBEDTLS_CMAC_C) - /** CMAC Specific context */ + /** CMAC-specific context. */ mbedtls_cmac_context_t *cmac_ctx; #endif } mbedtls_cipher_context_t; /** - * \brief Returns the list of ciphers supported by the generic cipher module. + * \brief This function retrieves the list of ciphers supported by the generic + * cipher module. * - * \return a statically allocated array of ciphers, the last entry - * is 0. + * \return A statically-allocated array of ciphers. The last entry + * is zero. */ const int *mbedtls_cipher_list( void ); /** - * \brief Returns the cipher information structure associated - * with the given cipher name. + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. * - * \param cipher_name Name of the cipher to search for. + * \param cipher_name Name of the cipher to search for. This must not be + * \c NULL. * - * \return the cipher information structure associated with the - * given cipher_name, or NULL if not found. + * \return The cipher information structure associated with the + * given \p cipher_name. + * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); /** - * \brief Returns the cipher information structure associated - * with the given cipher type. + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. * * \param cipher_type Type of the cipher to search for. * - * \return the cipher information structure associated with the - * given cipher_type, or NULL if not found. + * \return The cipher information structure associated with the + * given \p cipher_type. + * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); /** - * \brief Returns the cipher information structure associated - * with the given cipher id, key size and mode. + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. * - * \param cipher_id Id of the cipher to search for - * (e.g. MBEDTLS_CIPHER_ID_AES) - * \param key_bitlen Length of the key in bits - * \param mode Cipher mode (e.g. MBEDTLS_MODE_CBC) + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. * - * \return the cipher information structure associated with the - * given cipher_type, or NULL if not found. + * \return The cipher information structure associated with the + * given \p cipher_id. + * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode ); /** - * \brief Initialize a cipher_context (as NONE) + * \brief This function initializes a \p cipher_context as NONE. + * + * \param ctx The context to be initialized. This must not be \c NULL. */ void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); /** - * \brief Free and clear the cipher-specific context of ctx. - * Freeing ctx itself remains the responsibility of the - * caller. + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + * + * \param ctx The context to be freed. If this is \c NULL, the + * function has no effect, otherwise this must point to an + * initialized context. */ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); -/** - * \brief Initialises and fills the cipher context structure with - * the appropriate values. - * - * \note Currently also clears structure. In future versions you - * will be required to call mbedtls_cipher_init() on the structure - * first. - * - * \param ctx context to initialise. May not be NULL. - * \param cipher_info cipher to use. - * - * \return 0 on success, - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, - * MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the - * cipher-specific context failed. - */ -int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); /** - * \brief Returns the block size of the given cipher. + * \brief This function initializes and fills the cipher-context + * structure with the appropriate values. It also clears + * the structure. * - * \param ctx cipher's context. Must have been initialised. + * \param ctx The context to initialize. This must be initialized. + * \param cipher_info The cipher to use. * - * \return size of the cipher's blocks, or 0 if ctx has not been - * initialised. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. */ -static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ); + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The block size of the underlying cipher. + * \return \c 0 if \p ctx has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) return 0; return ctx->cipher_info->block_size; } /** - * \brief Returns the mode of operation for the cipher. - * (e.g. MBEDTLS_MODE_CBC) + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. * - * \param ctx cipher's context. Must have been initialised. + * \param ctx The context of the cipher. This must be initialized. * - * \return mode of operation, or MBEDTLS_MODE_NONE if ctx - * has not been initialised. + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. */ -static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE ); + if( ctx->cipher_info == NULL ) return MBEDTLS_MODE_NONE; return ctx->cipher_info->mode; } /** - * \brief Returns the size of the cipher's IV/NONCE in bytes. + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. * - * \param ctx cipher's context. Must have been initialised. + * \param ctx The context of the cipher. This must be initialized. * - * \return If IV has not been set yet: (recommended) IV size - * (0 for ciphers not using IV/NONCE). - * If IV has already been set: actual size. + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. */ -static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) +static inline int mbedtls_cipher_get_iv_size( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) return 0; if( ctx->iv_size != 0 ) @@ -383,254 +477,307 @@ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ct } /** - * \brief Returns the type of the given cipher. + * \brief This function returns the type of the given cipher. * - * \param ctx cipher's context. Must have been initialised. + * \param ctx The context of the cipher. This must be initialized. * - * \return type of the cipher, or MBEDTLS_CIPHER_NONE if ctx has - * not been initialised. + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. */ -static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_CIPHER_NONE ); + if( ctx->cipher_info == NULL ) return MBEDTLS_CIPHER_NONE; return ctx->cipher_info->type; } /** - * \brief Returns the name of the given cipher, as a string. + * \brief This function returns the name of the given cipher + * as a string. * - * \param ctx cipher's context. Must have been initialised. + * \param ctx The context of the cipher. This must be initialized. * - * \return name of the cipher, or NULL if ctx was not initialised. + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. */ -static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) +static inline const char *mbedtls_cipher_get_name( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) return 0; return ctx->cipher_info->name; } /** - * \brief Returns the key length of the cipher. + * \brief This function returns the key length of the cipher. * - * \param ctx cipher's context. Must have been initialised. + * \param ctx The context of the cipher. This must be initialized. * - * \return cipher's key length, in bits, or - * MBEDTLS_KEY_LENGTH_NONE if ctx has not been - * initialised. + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. */ -static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) +static inline int mbedtls_cipher_get_key_bitlen( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_KEY_LENGTH_NONE ); + if( ctx->cipher_info == NULL ) return MBEDTLS_KEY_LENGTH_NONE; return (int) ctx->cipher_info->key_bitlen; } /** - * \brief Returns the operation of the given cipher. + * \brief This function returns the operation of the given cipher. * - * \param ctx cipher's context. Must have been initialised. + * \param ctx The context of the cipher. This must be initialized. * - * \return operation (MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT), - * or MBEDTLS_OPERATION_NONE if ctx has not been - * initialised. + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. */ -static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) +static inline mbedtls_operation_t mbedtls_cipher_get_operation( + const mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_OPERATION_NONE ); + if( ctx->cipher_info == NULL ) return MBEDTLS_OPERATION_NONE; return ctx->operation; } /** - * \brief Set the key to use with the given context. + * \brief This function sets the key to use with the given context. * - * \param ctx generic cipher context. May not be NULL. Must have been - * initialised using cipher_context_from_type or - * cipher_context_from_string. - * \param key The key to use. - * \param key_bitlen key length to use, in bits. - * \param operation Operation that the key will be used for, either - * MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT. + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param key The key to use. This must be a readable buffer of at + * least \p key_bitlen Bits. + * \param key_bitlen The key length to use, in Bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails or a cipher specific - * error code. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. */ -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ); +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ); #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** - * \brief Set padding mode, for cipher modes that use padding. - * (Default: PKCS7 padding.) + * \brief This function sets the padding mode, for cipher modes + * that use padding. * - * \param ctx generic cipher context - * \param mode padding mode + * The default passing mode is PKCS7 padding. * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE - * if selected padding mode is not supported, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param mode The padding mode. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode * does not support padding. */ -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ); #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ /** - * \brief Set the initialization vector (IV) or nonce + * \brief This function sets the initialization vector (IV) + * or nonce. * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. * - * \returns 0 on success, or MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This + * must be a readable buffer of at least \p iv_len Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. * - * \note Some ciphers don't use IVs nor NONCE. For these - * ciphers, this function has no effect. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. */ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ); + const unsigned char *iv, + size_t iv_len ); /** - * \brief Finish preparation of the given context + * \brief This function resets the cipher state. * - * \param ctx generic cipher context + * \param ctx The generic cipher context. This must be initialized. * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA - * if parameter verification fails. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. */ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** - * \brief Add additional data (for AEAD ciphers). - * Currently only supported with GCM. - * Must be called exactly once, after mbedtls_cipher_reset(). + * \brief This function adds additional data for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called exactly once, after + * mbedtls_cipher_reset(). * - * \param ctx generic cipher context - * \param ad Additional data to use. - * \param ad_len Length of ad. + * \param ctx The generic cipher context. This must be initialized. + * \param ad The additional data to use. This must be a readable + * buffer of at least \p ad_len Bytes. + * \param ad_len the Length of \p ad Bytes. * - * \return 0 on success, or a specific error code. + * \return \c 0 on success. + * \return A specific error code on failure. */ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ); -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** - * \brief Generic cipher update function. Encrypts/decrypts - * using the given cipher context. Writes as many block - * size'd blocks of data as possible to output. Any data - * that cannot be written immediately will either be added - * to the next block, or flushed when cipher_final is - * called. - * Exception: for MBEDTLS_MODE_ECB, expects single block - * in size (e.g. 16 bytes for AES) + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. * - * \param ctx generic cipher context - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. Should be able to hold at - * least ilen + block_size. Cannot be the same buffer as - * input! - * \param olen length of the output data, will be filled with the - * actual number of bytes written. + * \note If the underlying cipher is used in GCM mode, all calls + * to this function, except for the last one before + * mbedtls_cipher_finish(), must have \p ilen as a + * multiple of the block size of the cipher. * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an - * unsupported mode for a cipher or a cipher specific - * error code. + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. * - * \note If the underlying cipher is GCM, all calls to this - * function, except the last one before mbedtls_cipher_finish(), - * must have ilen a multiple of the block size. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ); /** - * \brief Generic cipher finalisation function. If data still - * needs to be flushed from an incomplete block, data - * contained within it will be padded with the size of - * the last block, and written to the output buffer. + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. * - * \param ctx Generic cipher context - * \param output buffer to write data to. Needs block_size available. - * \param olen length of the data written to the output buffer. + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least \p block_size Bytes. + * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, - * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting or a cipher specific error code. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen ); -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** - * \brief Write tag for AEAD ciphers. - * Currently only supported with GCM. - * Must be called after mbedtls_cipher_finish(). + * \brief This function writes a tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). * - * \param ctx Generic cipher context - * \param tag buffer to write the tag - * \param tag_len Length of the tag to write + * \param ctx The generic cipher context. This must be initialized, + * bound to a key, and have just completed a cipher + * operation through mbedtls_cipher_finish() the tag for + * which should be written. + * \param tag The buffer to write the tag to. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to write. * - * \return 0 on success, or a specific error code. + * \return \c 0 on success. + * \return A specific error code on failure. */ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len ); /** - * \brief Check tag for AEAD ciphers. - * Currently only supported with GCM. - * Must be called after mbedtls_cipher_finish(). + * \brief This function checks the tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). * - * \param ctx Generic cipher context - * \param tag Buffer holding the tag - * \param tag_len Length of the tag to check + * \param ctx The generic cipher context. This must be initialized. + * \param tag The buffer holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to check. * - * \return 0 on success, or a specific error code. + * \return \c 0 on success. + * \return A specific error code on failure. */ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ); -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** - * \brief Generic all-in-one encryption/decryption - * (for all ciphers except AEAD constructs). + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. Should be able to hold at - * least ilen + block_size. Cannot be the same buffer as - * input! - * \param olen length of the output data, will be filled with the - * actual number of bytes written. + * \param ctx The generic cipher context. This must be initialized. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. * - * \note Some ciphers don't use IVs nor NONCE. For these - * ciphers, use iv = NULL and iv_len = 0. + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, or - * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting, or - * a cipher specific error code. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, @@ -639,26 +786,34 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, #if defined(MBEDTLS_CIPHER_MODE_AEAD) /** - * \brief Generic autenticated encryption (AEAD ciphers). + * \brief The generic autenticated encryption (AEAD) function. * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param ad Additional data to authenticate. - * \param ad_len Length of ad. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. - * Should be able to hold at least ilen. - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * \param tag buffer for the authentication tag - * \param tag_len desired tag length + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least \p ilen Bytes. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer for the authentication tag. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The desired length of the authentication tag. * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * a cipher specific error code. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, @@ -668,31 +823,39 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len ); /** - * \brief Generic autenticated decryption (AEAD ciphers). - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param ad Additional data to be authenticated. - * \param ad_len Length of ad. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. - * Should be able to hold at least ilen. - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * \param tag buffer holding the authentication tag - * \param tag_len length of the authentication tag - * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * MBEDTLS_ERR_CIPHER_AUTH_FAILED if data isn't authentic, - * or a cipher specific error code. + * \brief The generic autenticated decryption (AEAD) function. * * \note If the data is not authentic, then the output buffer - * is zeroed out to prevent the unauthentic plaintext to - * be used by mistake, making this interface safer. + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \param ctx The generic cipher context. This must be initialized and + * and bound to a key. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to be authenticated. This must be a + * readable buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * This must be able to hold at least \p ilen Bytes. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer holding the authentication tag. This must be + * a readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, diff --git a/Externals/mbedtls/include/mbedtls/cipher_internal.h b/Externals/mbedtls/include/mbedtls/cipher_internal.h index 6c58bcc525..c6def0bef7 100644 --- a/Externals/mbedtls/include/mbedtls/cipher_internal.h +++ b/Externals/mbedtls/include/mbedtls/cipher_internal.h @@ -4,7 +4,8 @@ * \brief Cipher wrappers. * * \author Adriaan de Jong - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -63,6 +64,14 @@ struct mbedtls_cipher_base_t unsigned char *output ); #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + #if defined(MBEDTLS_CIPHER_MODE_CTR) /** Encrypt using CTR */ int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, @@ -70,6 +79,13 @@ struct mbedtls_cipher_base_t const unsigned char *input, unsigned char *output ); #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + #if defined(MBEDTLS_CIPHER_MODE_STREAM) /** Encrypt using STREAM */ int (*stream_func)( void *ctx, size_t length, diff --git a/Externals/mbedtls/include/mbedtls/cmac.h b/Externals/mbedtls/include/mbedtls/cmac.h index 75e0b97c4a..9d42b3f209 100644 --- a/Externals/mbedtls/include/mbedtls/cmac.h +++ b/Externals/mbedtls/include/mbedtls/cmac.h @@ -1,10 +1,13 @@ /** * \file cmac.h * - * \brief Cipher-based Message Authentication Code (CMAC) Mode for - * Authentication + * \brief This file contains CMAC definitions and functions. * - * Copyright (C) 2015-2016, ARM Limited, All Rights Reserved + * The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. + */ +/* + * Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -19,113 +22,151 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H -#include "mbedtls/cipher.h" +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" #ifdef __cplusplus extern "C" { #endif +/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ + #define MBEDTLS_AES_BLOCK_SIZE 16 #define MBEDTLS_DES3_BLOCK_SIZE 8 #if defined(MBEDTLS_AES_C) -#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /* longest used by CMAC is AES */ +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ #else -#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */ +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ #endif +#if !defined(MBEDTLS_CMAC_ALT) + /** - * CMAC context structure - Contains internal state information only + * The CMAC context structure. */ struct mbedtls_cmac_context_t { - /** Internal state of the CMAC algorithm */ + /** The internal state of the CMAC algorithm. */ unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; /** Unprocessed data - either data that was not block aligned and is still - * pending to be processed, or the final block */ + * pending processing, or the final block. */ unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; - /** Length of data pending to be processed */ + /** The length of data pending processing. */ size_t unprocessed_len; }; +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + /** - * \brief Set the CMAC key and prepare to authenticate the input - * data. - * Should be called with an initialised cipher context. + * \brief This function sets the CMAC key, and prepares to authenticate + * the input data. + * Must be called with an initialized cipher context. * - * \param ctx Cipher context - * \param key CMAC key - * \param keybits length of the CMAC key in bits - * (must be acceptable by the cipher) + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. + * \param key The CMAC key. + * \param keybits The length of the CMAC key in bits. + * Must be supported by the cipher. * - * \return 0 if successful, or a cipher specific error code + * \return \c 0 on success. + * \return A cipher-specific error code on failure. */ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits ); /** - * \brief Generic CMAC process buffer. - * Called between mbedtls_cipher_cmac_starts() or - * mbedtls_cipher_cmac_reset() and - * mbedtls_cipher_cmac_finish(). - * May be called repeatedly. + * \brief This function feeds an input buffer into an ongoing CMAC + * computation. * - * \param ctx CMAC context - * \param input buffer holding the data - * \param ilen length of the input data + * It is called between mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset(), and mbedtls_cipher_cmac_finish(). + * Can be called repeatedly. * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The cipher context used for the CMAC operation. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. */ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen ); /** - * \brief Output CMAC. - * Called after mbedtls_cipher_cmac_update(). - * Usually followed by mbedtls_cipher_cmac_reset(), then - * mbedtls_cipher_cmac_starts(), or mbedtls_cipher_free(). + * \brief This function finishes the CMAC operation, and writes + * the result to the output buffer. * - * \param ctx CMAC context - * \param output Generic CMAC checksum result + * It is called after mbedtls_cipher_cmac_update(). + * It can be followed by mbedtls_cipher_cmac_reset() and + * mbedtls_cipher_cmac_update(), or mbedtls_cipher_free(). * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The cipher context used for the CMAC operation. + * \param output The output buffer for the CMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. */ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, unsigned char *output ); /** - * \brief Prepare to authenticate a new message with the same key. - * Called after mbedtls_cipher_cmac_finish() and before - * mbedtls_cipher_cmac_update(). + * \brief This function prepares the authentication of another + * message with the same key as the previous CMAC + * operation. * - * \param ctx CMAC context to be reset + * It is called after mbedtls_cipher_cmac_finish() + * and before mbedtls_cipher_cmac_update(). * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The cipher context used for the CMAC operation. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. */ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); /** - * \brief Output = Generic_CMAC( hmac key, input buffer ) + * \brief This function calculates the full generic CMAC + * on the input buffer with the provided key. * - * \param cipher_info message digest info - * \param key CMAC key - * \param keylen length of the CMAC key in bits - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic CMAC-result + * The function allocates the context, performs the + * calculation, and frees the context. * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * The CMAC result is calculated as + * output = generic CMAC(cmac key, input buffer). + * + * + * \param cipher_info The cipher information. + * \param key The CMAC key. + * \param keylen The length of the CMAC key in bits. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the generic CMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. */ int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, const unsigned char *key, size_t keylen, @@ -134,16 +175,21 @@ int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, #if defined(MBEDTLS_AES_C) /** - * \brief AES-CMAC-128-PRF - * Implementation of (AES-CMAC-PRF-128), as defined in RFC 4615 + * \brief This function implements the AES-CMAC-PRF-128 pseudorandom + * function, as defined in + * RFC-4615: The Advanced Encryption Standard-Cipher-based + * Message Authentication Code-Pseudo-Random Function-128 + * (AES-CMAC-PRF-128) Algorithm for the Internet Key + * Exchange Protocol (IKE). * - * \param key PRF key - * \param key_len PRF key length in bytes - * \param input buffer holding the input data - * \param in_len length of the input data in bytes - * \param output buffer holding the generated pseudorandom output (16 bytes) + * \param key The key to use. + * \param key_len The key length in Bytes. + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * \param output The buffer holding the generated 16 Bytes of + * pseudorandom output. * - * \return 0 if successful + * \return \c 0 on success. */ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, const unsigned char *input, size_t in_len, @@ -152,9 +198,10 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, #if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) /** - * \brief Checkup routine + * \brief The CMAC checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_cmac_self_test( int verbose ); #endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ diff --git a/Externals/mbedtls/include/mbedtls/compat-1.3.h b/Externals/mbedtls/include/mbedtls/compat-1.3.h index 27abbd9720..a58b47243d 100644 --- a/Externals/mbedtls/include/mbedtls/compat-1.3.h +++ b/Externals/mbedtls/include/mbedtls/compat-1.3.h @@ -5,7 +5,8 @@ * for the PolarSSL naming conventions. * * \deprecated Use the new names directly instead - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -24,6 +25,12 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) @@ -207,9 +214,6 @@ #if defined MBEDTLS_ERROR_C #define POLARSSL_ERROR_C MBEDTLS_ERROR_C #endif -#if defined MBEDTLS_ERROR_STRERROR_BC -#define POLARSSL_ERROR_STRERROR_BC MBEDTLS_ERROR_STRERROR_BC -#endif #if defined MBEDTLS_ERROR_STRERROR_DUMMY #define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY #endif @@ -318,9 +322,6 @@ #if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C #define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C #endif -#if defined MBEDTLS_MEMORY_C -#define POLARSSL_MEMORY_C MBEDTLS_MEMORY_C -#endif #if defined MBEDTLS_MEMORY_DEBUG #define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG #endif @@ -345,9 +346,6 @@ #if defined MBEDTLS_PADLOCK_C #define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C #endif -#if defined MBEDTLS_PBKDF2_C -#define POLARSSL_PBKDF2_C MBEDTLS_PBKDF2_C -#endif #if defined MBEDTLS_PEM_PARSE_C #define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C #endif @@ -429,9 +427,6 @@ #if defined MBEDTLS_PLATFORM_STD_FREE #define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE #endif -#if defined MBEDTLS_PLATFORM_STD_MALLOC -#define POLARSSL_PLATFORM_STD_MALLOC MBEDTLS_PLATFORM_STD_MALLOC -#endif #if defined MBEDTLS_PLATFORM_STD_MEM_HDR #define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR #endif @@ -492,12 +487,6 @@ #if defined MBEDTLS_SHA512_PROCESS_ALT #define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT #endif -#if defined MBEDTLS_SSL_AEAD_RANDOM_IV -#define POLARSSL_SSL_AEAD_RANDOM_IV MBEDTLS_SSL_AEAD_RANDOM_IV -#endif -#if defined MBEDTLS_SSL_ALERT_MESSAGES -#define POLARSSL_SSL_ALERT_MESSAGES MBEDTLS_SSL_ALERT_MESSAGES -#endif #if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES #define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES #endif @@ -522,9 +511,6 @@ #if defined MBEDTLS_SSL_DEBUG_ALL #define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL #endif -#if defined MBEDTLS_SSL_DISABLE_RENEGOTIATION -#define POLARSSL_SSL_DISABLE_RENEGOTIATION MBEDTLS_SSL_DISABLE_RENEGOTIATION -#endif #if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY #define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY #endif @@ -752,7 +738,6 @@ #define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT #define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION #define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 -#define MD_CONTEXT_T_INIT MBEDTLS_MD_CONTEXT_T_INIT #define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC #define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS #define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE @@ -1017,19 +1002,13 @@ #define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H #define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H #define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H -#define POLARSSL_DEBUG_LOG_FULL MBEDTLS_DEBUG_LOG_FULL -#define POLARSSL_DEBUG_LOG_RAW MBEDTLS_DEBUG_LOG_RAW #define POLARSSL_DECRYPT MBEDTLS_DECRYPT #define POLARSSL_DES_H MBEDTLS_DES_H #define POLARSSL_DHM_H MBEDTLS_DHM_H -#define POLARSSL_DHM_RFC2409_MODP_1024_G MBEDTLS_DHM_RFC2409_MODP_1024_G -#define POLARSSL_DHM_RFC2409_MODP_1024_P MBEDTLS_DHM_RFC2409_MODP_1024_P #define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G #define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P #define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G #define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P -#define POLARSSL_DHM_RFC5114_MODP_1024_G MBEDTLS_DHM_RFC5114_MODP_1024_G -#define POLARSSL_DHM_RFC5114_MODP_1024_P MBEDTLS_DHM_RFC5114_MODP_1024_P #define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G #define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P #define POLARSSL_ECDH_H MBEDTLS_ECDH_H @@ -1117,9 +1096,6 @@ #define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR #define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG #define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -#define POLARSSL_ERR_MD2_FILE_IO_ERROR MBEDTLS_ERR_MD2_FILE_IO_ERROR -#define POLARSSL_ERR_MD4_FILE_IO_ERROR MBEDTLS_ERR_MD4_FILE_IO_ERROR -#define POLARSSL_ERR_MD5_FILE_IO_ERROR MBEDTLS_ERR_MD5_FILE_IO_ERROR #define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED #define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA #define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE @@ -1147,7 +1123,6 @@ #define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL #define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND #define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -#define POLARSSL_ERR_PBKDF2_BAD_INPUT_DATA MBEDTLS_ERR_PBKDF2_BAD_INPUT_DATA #define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA #define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE #define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA @@ -1179,7 +1154,6 @@ #define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH #define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE #define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -#define POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR MBEDTLS_ERR_RIPEMD160_FILE_IO_ERROR #define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA #define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING #define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED @@ -1189,9 +1163,6 @@ #define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED #define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED #define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED -#define POLARSSL_ERR_SHA1_FILE_IO_ERROR MBEDTLS_ERR_SHA1_FILE_IO_ERROR -#define POLARSSL_ERR_SHA256_FILE_IO_ERROR MBEDTLS_ERR_SHA256_FILE_IO_ERROR -#define POLARSSL_ERR_SHA512_FILE_IO_ERROR MBEDTLS_ERR_SHA512_FILE_IO_ERROR #define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE #define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST #define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY @@ -1305,7 +1276,6 @@ #define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 #define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H #define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H -#define POLARSSL_MEMORY_H MBEDTLS_MEMORY_H #define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC #define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM #define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB @@ -1319,7 +1289,7 @@ #define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 #define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS #define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE -#define POLARSSL_NET_H MBEDTLS_NET_H +#define POLARSSL_NET_H MBEDTLS_NET_SOCKETS_H #define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG #define POLARSSL_OID_H MBEDTLS_OID_H #define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE @@ -1329,7 +1299,6 @@ #define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS #define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN #define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H -#define POLARSSL_PBKDF2_H MBEDTLS_PBKDF2_H #define POLARSSL_PEM_H MBEDTLS_PEM_H #define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H #define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H @@ -1415,7 +1384,8 @@ #define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED #define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED #define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED -#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN +#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \ + ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) #define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES #define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT #define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED @@ -1712,7 +1682,6 @@ #define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 #define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 #define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA -#define UL64 MBEDTLS_UL64 #define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 #define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 #define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 @@ -1736,7 +1705,6 @@ #define _ssl_key_cert mbedtls_ssl_key_cert #define _ssl_premaster_secret mbedtls_ssl_premaster_secret #define _ssl_session mbedtls_ssl_session -#define _ssl_ticket_keys mbedtls_ssl_ticket_keys #define _ssl_transform mbedtls_ssl_transform #define _x509_crl mbedtls_x509_crl #define _x509_crl_entry mbedtls_x509_crl_entry @@ -1836,7 +1804,6 @@ #define cipher_definitions mbedtls_cipher_definitions #define cipher_finish mbedtls_cipher_finish #define cipher_free mbedtls_cipher_free -#define cipher_free_ctx mbedtls_cipher_free_ctx #define cipher_get_block_size mbedtls_cipher_get_block_size #define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode #define cipher_get_iv_size mbedtls_cipher_get_iv_size @@ -1855,7 +1822,6 @@ #define cipher_mode_t mbedtls_cipher_mode_t #define cipher_padding_t mbedtls_cipher_padding_t #define cipher_reset mbedtls_cipher_reset -#define cipher_self_test mbedtls_cipher_self_test #define cipher_set_iv mbedtls_cipher_set_iv #define cipher_set_padding_mode mbedtls_cipher_set_padding_mode #define cipher_setkey mbedtls_cipher_setkey @@ -1866,7 +1832,6 @@ #define ctr_drbg_context mbedtls_ctr_drbg_context #define ctr_drbg_free mbedtls_ctr_drbg_free #define ctr_drbg_init mbedtls_ctr_drbg_init -#define ctr_drbg_init_entropy_len mbedtls_ctr_drbg_init_entropy_len #define ctr_drbg_random mbedtls_ctr_drbg_random #define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add #define ctr_drbg_reseed mbedtls_ctr_drbg_reseed @@ -1877,14 +1842,12 @@ #define ctr_drbg_update mbedtls_ctr_drbg_update #define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file #define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file -#define debug_fmt mbedtls_debug_fmt #define debug_print_buf mbedtls_debug_print_buf #define debug_print_crt mbedtls_debug_print_crt #define debug_print_ecp mbedtls_debug_print_ecp #define debug_print_mpi mbedtls_debug_print_mpi #define debug_print_msg mbedtls_debug_print_msg #define debug_print_ret mbedtls_debug_print_ret -#define debug_set_log_mode mbedtls_debug_set_log_mode #define debug_set_threshold mbedtls_debug_set_threshold #define des3_context mbedtls_des3_context #define des3_crypt_cbc mbedtls_des3_crypt_cbc @@ -1928,7 +1891,6 @@ #define ecdh_make_public mbedtls_ecdh_make_public #define ecdh_read_params mbedtls_ecdh_read_params #define ecdh_read_public mbedtls_ecdh_read_public -#define ecdh_self_test mbedtls_ecdh_self_test #define ecdh_side mbedtls_ecdh_side #define ecdsa_context mbedtls_ecdsa_context #define ecdsa_free mbedtls_ecdsa_free @@ -1937,7 +1899,6 @@ #define ecdsa_info mbedtls_ecdsa_info #define ecdsa_init mbedtls_ecdsa_init #define ecdsa_read_signature mbedtls_ecdsa_read_signature -#define ecdsa_self_test mbedtls_ecdsa_self_test #define ecdsa_sign mbedtls_ecdsa_sign #define ecdsa_sign_det mbedtls_ecdsa_sign_det #define ecdsa_verify mbedtls_ecdsa_verify @@ -1945,7 +1906,6 @@ #define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det #define eckey_info mbedtls_eckey_info #define eckeydh_info mbedtls_eckeydh_info -#define ecp_add mbedtls_ecp_add #define ecp_check_privkey mbedtls_ecp_check_privkey #define ecp_check_pub_priv mbedtls_ecp_check_pub_priv #define ecp_check_pubkey mbedtls_ecp_check_pubkey @@ -1962,7 +1922,6 @@ #define ecp_group_free mbedtls_ecp_group_free #define ecp_group_id mbedtls_ecp_group_id #define ecp_group_init mbedtls_ecp_group_init -#define ecp_group_read_string mbedtls_ecp_group_read_string #define ecp_grp_id_list mbedtls_ecp_grp_id_list #define ecp_is_zero mbedtls_ecp_is_zero #define ecp_keypair mbedtls_ecp_keypair @@ -1977,7 +1936,6 @@ #define ecp_point_write_binary mbedtls_ecp_point_write_binary #define ecp_self_test mbedtls_ecp_self_test #define ecp_set_zero mbedtls_ecp_set_zero -#define ecp_sub mbedtls_ecp_sub #define ecp_tls_read_group mbedtls_ecp_tls_read_group #define ecp_tls_read_point mbedtls_ecp_tls_read_point #define ecp_tls_write_group mbedtls_ecp_tls_write_group @@ -2015,7 +1973,6 @@ #define hmac_drbg_context mbedtls_hmac_drbg_context #define hmac_drbg_free mbedtls_hmac_drbg_free #define hmac_drbg_init mbedtls_hmac_drbg_init -#define hmac_drbg_init_buf mbedtls_hmac_drbg_init_buf #define hmac_drbg_random mbedtls_hmac_drbg_random #define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add #define hmac_drbg_reseed mbedtls_hmac_drbg_reseed @@ -2031,14 +1988,8 @@ #define md mbedtls_md #define md2 mbedtls_md2 #define md2_context mbedtls_md2_context -#define md2_file mbedtls_md2_file #define md2_finish mbedtls_md2_finish #define md2_free mbedtls_md2_free -#define md2_hmac mbedtls_md2_hmac -#define md2_hmac_finish mbedtls_md2_hmac_finish -#define md2_hmac_reset mbedtls_md2_hmac_reset -#define md2_hmac_starts mbedtls_md2_hmac_starts -#define md2_hmac_update mbedtls_md2_hmac_update #define md2_info mbedtls_md2_info #define md2_init mbedtls_md2_init #define md2_process mbedtls_md2_process @@ -2047,14 +1998,8 @@ #define md2_update mbedtls_md2_update #define md4 mbedtls_md4 #define md4_context mbedtls_md4_context -#define md4_file mbedtls_md4_file #define md4_finish mbedtls_md4_finish #define md4_free mbedtls_md4_free -#define md4_hmac mbedtls_md4_hmac -#define md4_hmac_finish mbedtls_md4_hmac_finish -#define md4_hmac_reset mbedtls_md4_hmac_reset -#define md4_hmac_starts mbedtls_md4_hmac_starts -#define md4_hmac_update mbedtls_md4_hmac_update #define md4_info mbedtls_md4_info #define md4_init mbedtls_md4_init #define md4_process mbedtls_md4_process @@ -2063,14 +2008,8 @@ #define md4_update mbedtls_md4_update #define md5 mbedtls_md5 #define md5_context mbedtls_md5_context -#define md5_file mbedtls_md5_file #define md5_finish mbedtls_md5_finish #define md5_free mbedtls_md5_free -#define md5_hmac mbedtls_md5_hmac -#define md5_hmac_finish mbedtls_md5_hmac_finish -#define md5_hmac_reset mbedtls_md5_hmac_reset -#define md5_hmac_starts mbedtls_md5_hmac_starts -#define md5_hmac_update mbedtls_md5_hmac_update #define md5_info mbedtls_md5_info #define md5_init mbedtls_md5_init #define md5_process mbedtls_md5_process @@ -2081,7 +2020,6 @@ #define md_file mbedtls_md_file #define md_finish mbedtls_md_finish #define md_free mbedtls_md_free -#define md_free_ctx mbedtls_md_free_ctx #define md_get_name mbedtls_md_get_name #define md_get_size mbedtls_md_get_size #define md_get_type mbedtls_md_get_type @@ -2109,7 +2047,6 @@ #define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status #define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify #define memory_buffer_set_verify mbedtls_memory_buffer_set_verify -#define memory_set_own mbedtls_memory_set_own #define mpi mbedtls_mpi #define mpi_add_abs mbedtls_mpi_add_abs #define mpi_add_int mbedtls_mpi_add_int @@ -2185,8 +2122,6 @@ #define padlock_supports mbedtls_padlock_has_support #define padlock_xcryptcbc mbedtls_padlock_xcryptcbc #define padlock_xcryptecb mbedtls_padlock_xcryptecb -#define pbkdf2_hmac mbedtls_pbkdf2_hmac -#define pbkdf2_self_test mbedtls_pbkdf2_self_test #define pem_context mbedtls_pem_context #define pem_free mbedtls_pem_free #define pem_init mbedtls_pem_init @@ -2246,13 +2181,11 @@ #define platform_entropy_poll mbedtls_platform_entropy_poll #define platform_set_exit mbedtls_platform_set_exit #define platform_set_fprintf mbedtls_platform_set_fprintf -#define platform_set_malloc_free mbedtls_platform_set_malloc_free #define platform_set_printf mbedtls_platform_set_printf #define platform_set_snprintf mbedtls_platform_set_snprintf #define polarssl_exit mbedtls_exit #define polarssl_fprintf mbedtls_fprintf #define polarssl_free mbedtls_free -#define polarssl_malloc mbedtls_malloc #define polarssl_mutex_free mbedtls_mutex_free #define polarssl_mutex_init mbedtls_mutex_init #define polarssl_mutex_lock mbedtls_mutex_lock @@ -2262,14 +2195,8 @@ #define polarssl_strerror mbedtls_strerror #define ripemd160 mbedtls_ripemd160 #define ripemd160_context mbedtls_ripemd160_context -#define ripemd160_file mbedtls_ripemd160_file #define ripemd160_finish mbedtls_ripemd160_finish #define ripemd160_free mbedtls_ripemd160_free -#define ripemd160_hmac mbedtls_ripemd160_hmac -#define ripemd160_hmac_finish mbedtls_ripemd160_hmac_finish -#define ripemd160_hmac_reset mbedtls_ripemd160_hmac_reset -#define ripemd160_hmac_starts mbedtls_ripemd160_hmac_starts -#define ripemd160_hmac_update mbedtls_ripemd160_hmac_update #define ripemd160_info mbedtls_ripemd160_info #define ripemd160_init mbedtls_ripemd160_init #define ripemd160_process mbedtls_ripemd160_process @@ -2283,12 +2210,10 @@ #define rsa_check_pubkey mbedtls_rsa_check_pubkey #define rsa_context mbedtls_rsa_context #define rsa_copy mbedtls_rsa_copy -#define rsa_decrypt_func mbedtls_rsa_decrypt_func #define rsa_free mbedtls_rsa_free #define rsa_gen_key mbedtls_rsa_gen_key #define rsa_info mbedtls_rsa_info #define rsa_init mbedtls_rsa_init -#define rsa_key_len_func mbedtls_rsa_key_len_func #define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt #define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt #define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign @@ -2306,19 +2231,12 @@ #define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext #define rsa_self_test mbedtls_rsa_self_test #define rsa_set_padding mbedtls_rsa_set_padding -#define rsa_sign_func mbedtls_rsa_sign_func #define safer_memcmp mbedtls_ssl_safer_memcmp #define set_alarm mbedtls_set_alarm #define sha1 mbedtls_sha1 #define sha1_context mbedtls_sha1_context -#define sha1_file mbedtls_sha1_file #define sha1_finish mbedtls_sha1_finish #define sha1_free mbedtls_sha1_free -#define sha1_hmac mbedtls_sha1_hmac -#define sha1_hmac_finish mbedtls_sha1_hmac_finish -#define sha1_hmac_reset mbedtls_sha1_hmac_reset -#define sha1_hmac_starts mbedtls_sha1_hmac_starts -#define sha1_hmac_update mbedtls_sha1_hmac_update #define sha1_info mbedtls_sha1_info #define sha1_init mbedtls_sha1_init #define sha1_process mbedtls_sha1_process @@ -2328,14 +2246,8 @@ #define sha224_info mbedtls_sha224_info #define sha256 mbedtls_sha256 #define sha256_context mbedtls_sha256_context -#define sha256_file mbedtls_sha256_file #define sha256_finish mbedtls_sha256_finish #define sha256_free mbedtls_sha256_free -#define sha256_hmac mbedtls_sha256_hmac -#define sha256_hmac_finish mbedtls_sha256_hmac_finish -#define sha256_hmac_reset mbedtls_sha256_hmac_reset -#define sha256_hmac_starts mbedtls_sha256_hmac_starts -#define sha256_hmac_update mbedtls_sha256_hmac_update #define sha256_info mbedtls_sha256_info #define sha256_init mbedtls_sha256_init #define sha256_process mbedtls_sha256_process @@ -2345,14 +2257,8 @@ #define sha384_info mbedtls_sha384_info #define sha512 mbedtls_sha512 #define sha512_context mbedtls_sha512_context -#define sha512_file mbedtls_sha512_file #define sha512_finish mbedtls_sha512_finish #define sha512_free mbedtls_sha512_free -#define sha512_hmac mbedtls_sha512_hmac -#define sha512_hmac_finish mbedtls_sha512_hmac_finish -#define sha512_hmac_reset mbedtls_sha512_hmac_reset -#define sha512_hmac_starts mbedtls_sha512_hmac_starts -#define sha512_hmac_update mbedtls_sha512_hmac_update #define sha512_info mbedtls_sha512_info #define sha512_init mbedtls_sha512_init #define sha512_process mbedtls_sha512_process @@ -2385,7 +2291,6 @@ #define ssl_cookie_setup mbedtls_ssl_cookie_setup #define ssl_cookie_write mbedtls_ssl_cookie_write #define ssl_cookie_write_t mbedtls_ssl_cookie_write_t -#define ssl_curve_is_acceptable mbedtls_ssl_curve_is_acceptable #define ssl_derive_keys mbedtls_ssl_derive_keys #define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check #define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update @@ -2453,7 +2358,6 @@ #define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support #define ssl_set_authmode mbedtls_ssl_conf_authmode #define ssl_set_bio mbedtls_ssl_set_bio -#define ssl_set_bio mbedtls_ssl_set_bio_timeout #define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain #define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting #define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites @@ -2476,8 +2380,6 @@ #define ssl_set_max_version mbedtls_ssl_conf_max_version #define ssl_set_min_version mbedtls_ssl_conf_min_version #define ssl_set_own_cert mbedtls_ssl_conf_own_cert -#define ssl_set_own_cert_alt mbedtls_ssl_set_own_cert_alt -#define ssl_set_own_cert_rsa mbedtls_ssl_set_own_cert_rsa #define ssl_set_psk mbedtls_ssl_conf_psk #define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb #define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation @@ -2486,7 +2388,6 @@ #define ssl_set_rng mbedtls_ssl_conf_rng #define ssl_set_session mbedtls_ssl_set_session #define ssl_set_session_cache mbedtls_ssl_conf_session_cache -#define ssl_set_session_ticket_lifetime mbedtls_ssl_conf_session_ticket_lifetime #define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets #define ssl_set_sni mbedtls_ssl_conf_sni #define ssl_set_transport mbedtls_ssl_conf_transport @@ -2494,7 +2395,6 @@ #define ssl_set_verify mbedtls_ssl_conf_verify #define ssl_sig_from_pk mbedtls_ssl_sig_from_pk #define ssl_states mbedtls_ssl_states -#define ssl_ticket_keys mbedtls_ssl_ticket_keys #define ssl_transform mbedtls_ssl_transform #define ssl_transform_free mbedtls_ssl_transform_free #define ssl_write mbedtls_ssl_write @@ -2523,7 +2423,6 @@ #define test_cli_key mbedtls_test_cli_key #define test_cli_key_ec mbedtls_test_cli_key_ec #define test_cli_key_rsa mbedtls_test_cli_key_rsa -#define test_dhm_params mbedtls_test_dhm_params #define test_srv_crt mbedtls_test_srv_crt #define test_srv_crt_ec mbedtls_test_srv_crt_ec #define test_srv_crt_rsa mbedtls_test_srv_crt_rsa @@ -2578,8 +2477,6 @@ #define x509_get_time mbedtls_x509_get_time #define x509_key_size_helper mbedtls_x509_key_size_helper #define x509_name mbedtls_x509_name -#define x509_oid_get_description mbedtls_x509_oid_get_description -#define x509_oid_get_numeric_string mbedtls_x509_oid_get_numeric_string #define x509_self_test mbedtls_x509_self_test #define x509_sequence mbedtls_x509_sequence #define x509_serial_gets mbedtls_x509_serial_gets diff --git a/Externals/mbedtls/include/mbedtls/config.h b/Externals/mbedtls/include/mbedtls/config.h index 6fc9c772ae..654f9725e4 100644 --- a/Externals/mbedtls/include/mbedtls/config.h +++ b/Externals/mbedtls/include/mbedtls/config.h @@ -6,8 +6,9 @@ * This set of compile-time options may be used to enable * or disable features selectively, and reduce the global * memory footprint. - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -47,14 +48,68 @@ * Requires support for asm() in compiler. * * Used in: + * library/aria.c * library/timing.c - * library/padlock.c * include/mbedtls/bn_mul.h * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * * Comment to disable the use of assembly code. */ #define MBEDTLS_HAVE_ASM +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + /** * \def MBEDTLS_HAVE_SSE2 * @@ -82,12 +137,21 @@ /** * \def MBEDTLS_HAVE_TIME_DATE * - * System has time.h and time(), gmtime() and the clock is correct. + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). * The time needs to be correct (not necesarily very accurate, but at least * the date should be correct). This is used to verify the validity period of * X.509 certificates. * * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. */ #define MBEDTLS_HAVE_TIME_DATE @@ -163,6 +227,7 @@ //#define MBEDTLS_PLATFORM_PRINTF_ALT //#define MBEDTLS_PLATFORM_SNPRINTF_ALT //#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT /** * \def MBEDTLS_DEPRECATED_WARNING @@ -191,6 +256,48 @@ */ //#define MBEDTLS_DEPRECATED_REMOVED +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - the pointer is checked to be non-NULL only if this option is enabled + * - the content of the buffer is always validated + * + * When this flag is defined, if a library function receives a parameter that + * is invalid, it will: + * - invoke the macro MBEDTLS_PARAM_FAILED() which by default expands to a + * call to the function mbedtls_param_failed() + * - immediately return (with a specific error code unless the function + * returns void and can't communicate an error). + * + * When defining this flag, you also need to: + * - either provide a definition of the function mbedtls_param_failed() in + * your application (see platform_util.h for its prototype) as the library + * calls that function, but does not provide a default definition for it, + * - or provide a different definition of the macro MBEDTLS_PARAM_FAILED() + * below if the above mechanism is not flexible enough to suit your needs. + * See the documentation of this macro later in this file. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + /* \} name SECTION: System support */ /** @@ -218,34 +325,62 @@ * \def MBEDTLS_AES_ALT * * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your - * alternate core implementation of a symmetric crypto or hash module (e.g. - * platform specific assembly optimized implementations). Keep in mind that - * the function prototypes should remain the same. + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. * * This replaces the whole module. If you only want to replace one of the * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. * * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer - * provide the "struct mbedtls_aes_context" definition and omit the base function - * declarations and implementations. "aes_alt.h" will be included from + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from * "aes.h" to include the new function definitions. * * Uncomment a macro to enable alternate implementation of the corresponding * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * */ //#define MBEDTLS_AES_ALT //#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT //#define MBEDTLS_BLOWFISH_ALT //#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT //#define MBEDTLS_DES_ALT -//#define MBEDTLS_XTEA_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT //#define MBEDTLS_MD2_ALT //#define MBEDTLS_MD4_ALT //#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT //#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT //#define MBEDTLS_SHA1_ALT //#define MBEDTLS_SHA256_ALT //#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT /** * \def MBEDTLS_MD2_PROCESS_ALT @@ -263,12 +398,24 @@ * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible * with this definition. * - * Note: if you use the AES_xxx_ALT macros, then is is recommended to also set - * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES - * tables. + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. * * Uncomment a macro to enable alternate implementation of the corresponding * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * */ //#define MBEDTLS_MD2_PROCESS_ALT //#define MBEDTLS_MD4_PROCESS_ALT @@ -284,6 +431,64 @@ //#define MBEDTLS_AES_SETKEY_DEC_ALT //#define MBEDTLS_AES_ENCRYPT_ALT //#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT /** * \def MBEDTLS_TEST_NULL_ENTROPY @@ -318,12 +523,45 @@ /** * \def MBEDTLS_AES_ROM_TABLES * - * Store the AES tables in ROM. + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. * - * Uncomment this macro to store the AES tables in ROM. */ //#define MBEDTLS_AES_ROM_TABLES +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + /** * \def MBEDTLS_CAMELLIA_SMALL_MEMORY * @@ -354,6 +592,20 @@ */ #define MBEDTLS_CIPHER_MODE_CTR +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + /** * \def MBEDTLS_CIPHER_NULL_CIPHER * @@ -415,6 +667,9 @@ * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA * * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. */ //#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES @@ -431,6 +686,26 @@ */ #define MBEDTLS_REMOVE_ARC4_CIPHERSUITES +/** + * \def MBEDTLS_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible + * to enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including + * them explicitly. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES + /** * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED * @@ -451,6 +726,7 @@ #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED #define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED /** * \def MBEDTLS_ECP_NIST_OPTIM @@ -463,6 +739,30 @@ */ #define MBEDTLS_ECP_NIST_OPTIM +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + /** * \def MBEDTLS_ECDSA_DETERMINISTIC * @@ -520,6 +820,13 @@ * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * */ #define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED @@ -619,6 +926,13 @@ * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * */ #define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED @@ -910,7 +1224,8 @@ /** * \def MBEDTLS_RSA_NO_CRT * - * Do not use the Chinese Remainder Theorem for the RSA private operation. + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. * * Uncomment this macro to disable the use of CRT in RSA. * @@ -954,6 +1269,17 @@ */ #define MBEDTLS_SSL_ALL_ALERT_MESSAGES +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + /** * \def MBEDTLS_SSL_DEBUG_ALL * @@ -1048,7 +1374,7 @@ /** * \def MBEDTLS_SSL_RENEGOTIATION * - * Disable support for TLS renegotiation. + * Enable support for TLS renegotiation. * * The two main uses of renegotiation are (1) refresh keys on long-lived * connections and (2) client authentication after the initial handshake. @@ -1057,6 +1383,13 @@ * misuse/misunderstand. * * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * */ #define MBEDTLS_SSL_RENEGOTIATION @@ -1265,6 +1598,30 @@ */ #define MBEDTLS_SSL_TRUNCATED_HMAC +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + /** * \def MBEDTLS_THREADING_ALT * @@ -1371,6 +1728,9 @@ * * \note Currently compression can't be used with DTLS. * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * * Used in: library/ssl_tls.c * library/ssl_cli.c * library/ssl_srv.c @@ -1409,7 +1769,7 @@ * Enable the AES block cipher. * * Module: library/aes.c - * Caller: library/ssl_tls.c + * Caller: library/cipher.c * library/pem.c * library/ctr_drbg.c * @@ -1484,7 +1844,7 @@ * Enable the ARCFOUR stream cipher. * * Module: library/arc4.c - * Caller: library/ssl_tls.c + * Caller: library/cipher.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): @@ -1498,6 +1858,11 @@ * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * */ #define MBEDTLS_ARC4_C @@ -1525,7 +1890,7 @@ * library/pkwrite.c * library/x509_create.c * library/x509write_crt.c - * library/mbedtls_x509write_csr.c + * library/x509write_csr.c */ #define MBEDTLS_ASN1_WRITE_C @@ -1551,6 +1916,7 @@ * library/ecp.c * library/ecdsa.c * library/rsa.c + * library/rsa_internal.c * library/ssl_tls.c * * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. @@ -1572,7 +1938,7 @@ * Enable the Camellia block cipher. * * Module: library/camellia.c - * Caller: library/ssl_tls.c + * Caller: library/cipher.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): @@ -1621,6 +1987,58 @@ */ #define MBEDTLS_CAMELLIA_C +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + /** * \def MBEDTLS_CCM_C * @@ -1647,6 +2065,26 @@ */ #define MBEDTLS_CERTS_C +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + /** * \def MBEDTLS_CIPHER_C * @@ -1675,14 +2113,16 @@ /** * \def MBEDTLS_CTR_DRBG_C * - * Enable the CTR_DRBG AES-256-based random generator. + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below. * * Module: library/ctr_drbg.c * Caller: * * Requires: MBEDTLS_AES_C * - * This module provides the CTR_DRBG AES-256 random number generator. + * This module provides the CTR_DRBG AES random number generator. */ #define MBEDTLS_CTR_DRBG_C @@ -1707,7 +2147,7 @@ * * Module: library/des.c * Caller: library/pem.c - * library/ssl_tls.c + * library/cipher.c * * This module enables the following ciphersuites (if other requisites are * enabled as well): @@ -1723,6 +2163,9 @@ * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA * * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. */ #define MBEDTLS_DES_C @@ -1737,6 +2180,13 @@ * * This module is used by the following key exchanges: * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * */ #define MBEDTLS_DHM_C @@ -1867,6 +2317,21 @@ */ //#define MBEDTLS_HAVEGE_C +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + /** * \def MBEDTLS_HMAC_DRBG_C * @@ -1881,12 +2346,25 @@ */ #define MBEDTLS_HMAC_DRBG_C +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + /** * \def MBEDTLS_MD_C * * Enable the generic message digest layer. * - * Module: library/mbedtls_md.c + * Module: library/md.c * Caller: * * Uncomment to enable generic message digest wrappers. @@ -1898,10 +2376,15 @@ * * Enable the MD2 hash algorithm. * - * Module: library/mbedtls_md2.c + * Module: library/md2.c * Caller: * * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * */ //#define MBEDTLS_MD2_C @@ -1910,10 +2393,15 @@ * * Enable the MD4 hash algorithm. * - * Module: library/mbedtls_md4.c + * Module: library/md4.c * Caller: * * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * */ //#define MBEDTLS_MD4_C @@ -1922,13 +2410,20 @@ * * Enable the MD5 hash algorithm. * - * Module: library/mbedtls_md5.c - * Caller: library/mbedtls_md.c + * Module: library/md5.c + * Caller: library/md.c * library/pem.c * library/ssl_tls.c * - * This module is required for SSL/TLS and X.509. - * PEM_PARSE uses MD5 for decrypting encrypted keys. + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * */ #define MBEDTLS_MD5_C @@ -1980,11 +2475,11 @@ * library/rsa.c * library/x509.c * library/x509_create.c - * library/mbedtls_x509_crl.c - * library/mbedtls_x509_crt.c - * library/mbedtls_x509_csr.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c * library/x509write_crt.c - * library/mbedtls_x509write_csr.c + * library/x509write_csr.c * * This modules translates between OIDs and internal values. */ @@ -2012,9 +2507,9 @@ * Module: library/pem.c * Caller: library/dhm.c * library/pkparse.c - * library/mbedtls_x509_crl.c - * library/mbedtls_x509_crt.c - * library/mbedtls_x509_csr.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c * * Requires: MBEDTLS_BASE64_C * @@ -2030,7 +2525,7 @@ * Module: library/pem.c * Caller: library/pkwrite.c * library/x509write_crt.c - * library/mbedtls_x509write_csr.c + * library/x509write_csr.c * * Requires: MBEDTLS_BASE64_C * @@ -2060,8 +2555,8 @@ * Enable the generic public (asymetric) key parser. * * Module: library/pkparse.c - * Caller: library/mbedtls_x509_crt.c - * library/mbedtls_x509_csr.c + * Caller: library/x509_crt.c + * library/x509_csr.c * * Requires: MBEDTLS_PK_C * @@ -2147,13 +2642,23 @@ */ #define MBEDTLS_PLATFORM_C +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + /** * \def MBEDTLS_RIPEMD160_C * * Enable the RIPEMD-160 hash algorithm. * - * Module: library/mbedtls_ripemd160.c - * Caller: library/mbedtls_md.c + * Module: library/ripemd160.c + * Caller: library/md.c * */ #define MBEDTLS_RIPEMD160_C @@ -2164,6 +2669,7 @@ * Enable the RSA public-key cryptosystem. * * Module: library/rsa.c + * library/rsa_internal.c * Caller: library/ssl_cli.c * library/ssl_srv.c * library/ssl_tls.c @@ -2181,14 +2687,20 @@ * * Enable the SHA1 cryptographic hash algorithm. * - * Module: library/mbedtls_sha1.c - * Caller: library/mbedtls_md.c + * Module: library/sha1.c + * Caller: library/md.c * library/ssl_cli.c * library/ssl_srv.c * library/ssl_tls.c * library/x509write_crt.c * - * This module is required for SSL/TLS and SHA1-signed certificates. + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * */ #define MBEDTLS_SHA1_C @@ -2197,9 +2709,9 @@ * * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. * - * Module: library/mbedtls_sha256.c + * Module: library/sha256.c * Caller: library/entropy.c - * library/mbedtls_md.c + * library/md.c * library/ssl_cli.c * library/ssl_srv.c * library/ssl_tls.c @@ -2214,9 +2726,9 @@ * * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. * - * Module: library/mbedtls_sha512.c + * Module: library/sha512.c * Caller: library/entropy.c - * library/mbedtls_md.c + * library/md.c * library/ssl_cli.c * library/ssl_srv.c * @@ -2364,9 +2876,9 @@ * Enable X.509 core for using certificates. * * Module: library/x509.c - * Caller: library/mbedtls_x509_crl.c - * library/mbedtls_x509_crt.c - * library/mbedtls_x509_csr.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c * * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, * MBEDTLS_PK_PARSE_C @@ -2380,7 +2892,7 @@ * * Enable X.509 certificate parsing. * - * Module: library/mbedtls_x509_crt.c + * Module: library/x509_crt.c * Caller: library/ssl_cli.c * library/ssl_srv.c * library/ssl_tls.c @@ -2396,8 +2908,8 @@ * * Enable X.509 CRL parsing. * - * Module: library/mbedtls_x509_crl.c - * Caller: library/mbedtls_x509_crt.c + * Module: library/x509_crl.c + * Caller: library/x509_crt.c * * Requires: MBEDTLS_X509_USE_C * @@ -2410,7 +2922,7 @@ * * Enable X.509 Certificate Signing Request (CSR) parsing. * - * Module: library/mbedtls_x509_csr.c + * Module: library/x509_csr.c * Caller: library/x509_crt_write.c * * Requires: MBEDTLS_X509_USE_C @@ -2495,6 +3007,7 @@ //#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ //#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ //#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */ /* HMAC_DRBG options */ //#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ @@ -2545,12 +3058,134 @@ //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, a default definition is + * provided that invokes the function mbedtls_param_failed(), + * which is declared in platform_util.h for the benefit of the + * library, but that you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + /* SSL Cache options */ //#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ /* SSL options */ -//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum length (in bytes) of incoming and outgoing plaintext fragments. + * + * This determines the size of both the incoming and outgoing TLS I/O buffers + * in such a way that both are capable of holding the specified amount of + * plaintext data, regardless of the protection mechanism used. + * + * To configure incoming and outgoing I/O buffers separately, use + * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, + * which overwrite the value set by this option. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of both + * incoming and outgoing I/O buffers. + */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option is undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer + * independently of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * If this option undefined, it inherits its value from + * #MBEDTLS_SSL_MAX_CONTENT_LEN. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer + * independently of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + //#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ //#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ //#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ @@ -2573,25 +3208,84 @@ //#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ //#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + /* \} name SECTION: Customisation configuration options */ -/* Target and application specific configurations */ -//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h" - -#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE) -#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE -#endif - -/* +/* Target and application specific configurations + * * Allow user to override any previous default. * - * Use two macro names for that, as: - * - with yotta the prefix YOTTA_CFG_ is forced - * - without yotta is looks weird to have a YOTTA prefix. */ -#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) -#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE -#elif defined(MBEDTLS_USER_CONFIG_FILE) +#if defined(MBEDTLS_USER_CONFIG_FILE) #include MBEDTLS_USER_CONFIG_FILE #endif diff --git a/Externals/mbedtls/include/mbedtls/ctr_drbg.h b/Externals/mbedtls/include/mbedtls/ctr_drbg.h index 059d3c5c9a..cc3df7b113 100644 --- a/Externals/mbedtls/include/mbedtls/ctr_drbg.h +++ b/Externals/mbedtls/include/mbedtls/ctr_drbg.h @@ -1,9 +1,21 @@ /** * \file ctr_drbg.h * - * \brief CTR_DRBG based on AES-256 (NIST SP 800-90) + * \brief This file contains CTR_DRBG definitions and functions. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 + * as the underlying block cipher. + * + * \warning Using 128-bit keys for CTR_DRBG limits the security of generated + * keys and operations that use random values generated to 128-bit security. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,90 +30,120 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_CTR_DRBG_H #define MBEDTLS_CTR_DRBG_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "aes.h" #if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" +#include "threading.h" #endif #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ -#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */ -#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */ -#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ -#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */ -#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */ -#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) -#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) - /**< The seed length (counter + AES key) */ +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +#define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size used by the cipher (compile-time choice: 128 bits). */ +#else +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher (compile-time choice: 256 bits). */ +#endif + +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in config.h or define them using the compiler command + * line. * \{ */ #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 +/**< The amount of entropy used per seed by default: + *
  • 48 with SHA-512.
  • + *
  • 32 with SHA-256.
+ */ #else -#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +/**< Amount of entropy used per seed by default: + *
  • 48 with SHA-512.
  • + *
  • 32 with SHA-256.
+ */ #endif #endif #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) -#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) -#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) -#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) -#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer. */ #endif /* \} name SECTION: Module settings */ -#define MBEDTLS_CTR_DRBG_PR_OFF 0 /**< No prediction resistance */ -#define MBEDTLS_CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */ +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ #ifdef __cplusplus extern "C" { #endif /** - * \brief CTR_DRBG context structure + * \brief The CTR_DRBG context structure. */ -typedef struct +typedef struct mbedtls_ctr_drbg_context { - unsigned char counter[16]; /*!< counter (V) */ - int reseed_counter; /*!< reseed counter */ - int prediction_resistance; /*!< enable prediction resistance (Automatic - reseed before every random generation) */ - size_t entropy_len; /*!< amount of entropy grabbed on each - (re)seed */ - int reseed_interval; /*!< reseed interval */ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation. */ + int reseed_interval; /*!< The reseed interval. */ - mbedtls_aes_context aes_ctx; /*!< AES context */ + mbedtls_aes_context aes_ctx; /*!< The AES context. */ /* * Callbacks (Entropy) */ int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ - void *p_entropy; /*!< context for the entropy function */ + void *p_entropy; /*!< The context for the entropy function. */ #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t mutex; @@ -110,31 +152,32 @@ typedef struct mbedtls_ctr_drbg_context; /** - * \brief CTR_DRBG context initialization - * Makes the context ready for mbedtls_ctr_drbg_seed() or - * mbedtls_ctr_drbg_free(). + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). * - * \param ctx CTR_DRBG context to be initialized + * \param ctx The CTR_DRBG context to initialize. */ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); /** - * \brief CTR_DRBG initial seeding - * Seed and setup entropy source for future reseeds. + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. * - * Note: Personalization data can be provided in addition to the more generic - * entropy source to make this instantiation as unique as possible. + * \note Personalization data can be provided in addition to the more generic + * entropy source, to make this instantiation as unique as possible. * - * \param ctx CTR_DRBG context to be seeded - * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer - * length) - * \param p_entropy Entropy context - * \param custom Personalization data (Device specific identifiers) - * (Can be NULL) - * \param len Length of personalization data + * \param ctx The CTR_DRBG context to seed. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + length of the buffer. + * \param p_entropy The entropy context. + * \param custom Personalization data, that is device-specific + identifiers. Can be NULL. + * \param len The length of the personalization data. * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. */ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), @@ -143,141 +186,188 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, size_t len ); /** - * \brief Clear CTR_CRBG context data + * \brief This function clears CTR_CRBG context data. * - * \param ctx CTR_DRBG context to clear + * \param ctx The CTR_DRBG context to clear. */ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); /** - * \brief Enable / disable prediction resistance (Default: Off) + * \brief This function turns prediction resistance on or off. + * The default value is off. * - * Note: If enabled, entropy is used for ctx->entropy_len before each call! - * Only use this if you have ample supply of good entropy! + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add(). + * Only use this if your entropy source has sufficient + * throughput. * - * \param ctx CTR_DRBG context - * \param resistance MBEDTLS_CTR_DRBG_PR_ON or MBEDTLS_CTR_DRBG_PR_OFF + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. */ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ); /** - * \brief Set the amount of entropy grabbed on each (re)seed - * (Default: MBEDTLS_CTR_DRBG_ENTROPY_LEN) + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. The default value is + * #MBEDTLS_CTR_DRBG_ENTROPY_LEN. * - * \param ctx CTR_DRBG context - * \param len Amount of entropy to grab + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab. */ void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ); /** - * \brief Set the reseed interval - * (Default: MBEDTLS_CTR_DRBG_RESEED_INTERVAL) + * \brief This function sets the reseed interval. + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. * - * \param ctx CTR_DRBG context - * \param interval Reseed interval + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. */ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ); /** - * \brief CTR_DRBG reseeding (extracts data from entropy source) + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. * - * \param ctx CTR_DRBG context - * \param additional Additional data to add to state (Can be NULL) - * \param len Length of additional data + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be NULL. + * \param len The length of the additional data. * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. */ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len ); /** - * \brief CTR_DRBG update state + * \brief This function updates the state of the CTR_DRBG context. * - * \param ctx CTR_DRBG context - * \param additional Additional data to update state with - * \param add_len Length of additional data + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * - * \note If add_len is greater than MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, - * only the first MBEDTLS_CTR_DRBG_MAX_SEED_INPUT bytes are used, - * the remaining ones are silently discarded. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. */ -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); /** - * \brief CTR_DRBG generate random with additional update input + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. * - * Note: Automatically reseeds if reseed_counter is reached. + * \note The function automatically reseeds if the reseed counter is exceeded. * - * \param p_rng CTR_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * \param additional Additional data to update with (Can be NULL) - * \param add_len Length of additional data + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * \param additional Additional data to update. Can be NULL. + * \param add_len The length of the additional data. * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. */ int mbedtls_ctr_drbg_random_with_add( void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len ); /** - * \brief CTR_DRBG generate random + * \brief This function uses CTR_DRBG to generate random data. * - * Note: Automatically reseeds if reseed_counter is reached. + * \note The function automatically reseeds if the reseed counter is exceeded. * - * \param p_rng CTR_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. */ int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \deprecated Superseded by mbedtls_ctr_drbg_update_ret() + * in 2.16.0. + * + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + */ +MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update( + mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + #if defined(MBEDTLS_FS_IO) /** - * \brief Write a seed file + * \brief This function writes a seed file. * - * \param ctx CTR_DRBG context - * \param path Name of the file + * \param ctx The CTR_DRBG context. + * \param path The name of the file. * - * \return 0 if successful, - * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * failure. */ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); /** - * \brief Read and update a seed file. Seed is added to this - * instance + * \brief This function reads and updates a seed file. The seed + * is added to this instance. * - * \param ctx CTR_DRBG context - * \param path Name of the file + * \param ctx The CTR_DRBG context. + * \param path The name of the file. * - * \return 0 if successful, - * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or - * MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure. */ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); #endif /* MBEDTLS_FS_IO */ +#if defined(MBEDTLS_SELF_TEST) + /** - * \brief Checkup routine + * \brief The CTR_DRBG checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_ctr_drbg_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + /* Internal functions (do not call directly) */ int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, int (*)(void *, unsigned char *, size_t), void *, diff --git a/Externals/mbedtls/include/mbedtls/debug.h b/Externals/mbedtls/include/mbedtls/debug.h index 2957996407..736444bb76 100644 --- a/Externals/mbedtls/include/mbedtls/debug.h +++ b/Externals/mbedtls/include/mbedtls/debug.h @@ -2,7 +2,8 @@ * \file debug.h * * \brief Functions for controlling and providing debug output from the library. - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -64,6 +65,11 @@ mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) #endif +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \ + mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr ) +#endif + #else /* MBEDTLS_DEBUG_C */ #define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) @@ -72,6 +78,7 @@ #define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) #define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 ) #endif /* MBEDTLS_DEBUG_C */ @@ -220,6 +227,36 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, const char *text, const mbedtls_x509_crt *crt ); #endif +#if defined(MBEDTLS_ECDH_C) +typedef enum +{ + MBEDTLS_DEBUG_ECDH_Q, + MBEDTLS_DEBUG_ECDH_QP, + MBEDTLS_DEBUG_ECDH_Z, +} mbedtls_debug_ecdh_attr; + +/** + * \brief Print a field of the ECDH structure in the SSL context to the debug + * output. This function is always used through the + * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file + * and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param ecdh the ECDH context + * \param attr the identifier of the attribute being output + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ); +#endif + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/des.h b/Externals/mbedtls/include/mbedtls/des.h index 5ca2ecf2e0..54e6b7894b 100644 --- a/Externals/mbedtls/include/mbedtls/des.h +++ b/Externals/mbedtls/include/mbedtls/des.h @@ -3,6 +3,11 @@ * * \brief DES block cipher * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -19,6 +24,7 @@ * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) + * */ #ifndef MBEDTLS_DES_H #define MBEDTLS_DES_H @@ -37,20 +43,27 @@ #define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ -#define MBEDTLS_DES_KEY_SIZE 8 +/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ -#if !defined(MBEDTLS_DES_ALT) -// Regular implementation -// +#define MBEDTLS_DES_KEY_SIZE 8 #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + /** * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ -typedef struct +typedef struct mbedtls_des_context { uint32_t sk[32]; /*!< DES subkeys */ } @@ -59,16 +72,24 @@ mbedtls_des_context; /** * \brief Triple-DES context structure */ -typedef struct +typedef struct mbedtls_des3_context { uint32_t sk[96]; /*!< 3DES subkeys */ } mbedtls_des3_context; +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + /** * \brief Initialize DES context * * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ void mbedtls_des_init( mbedtls_des_context *ctx ); @@ -76,6 +97,10 @@ void mbedtls_des_init( mbedtls_des_context *ctx ); * \brief Clear DES context * * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ void mbedtls_des_free( mbedtls_des_context *ctx ); @@ -100,6 +125,10 @@ void mbedtls_des3_free( mbedtls_des3_context *ctx ); * a parity bit to allow verification. * * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); @@ -112,6 +141,10 @@ void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); * \param key 8-byte secret key * * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); @@ -121,6 +154,10 @@ int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SI * \param key 8-byte secret key * * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); @@ -131,6 +168,10 @@ int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); * \param key 8-byte secret key * * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); @@ -141,6 +182,10 @@ int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MB * \param key 8-byte secret key * * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); @@ -196,6 +241,10 @@ int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, * \param output 64-bit output block * * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, const unsigned char input[8], @@ -219,6 +268,10 @@ int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, * \param iv initialization vector (updated after use) * \param input buffer holding the input data * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, int mode, @@ -277,20 +330,15 @@ int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, * * \param SK Round keys * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. */ void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); -#ifdef __cplusplus -} -#endif -#else /* MBEDTLS_DES_ALT */ -#include "des_alt.h" -#endif /* MBEDTLS_DES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine @@ -299,6 +347,8 @@ extern "C" { */ int mbedtls_des_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/dhm.h b/Externals/mbedtls/include/mbedtls/dhm.h index d7ab1522ec..2909f5fbc8 100644 --- a/Externals/mbedtls/include/mbedtls/dhm.h +++ b/Externals/mbedtls/include/mbedtls/dhm.h @@ -1,9 +1,50 @@ /** * \file dhm.h * - * \brief Diffie-Hellman-Merkle key exchange + * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange + * definitions and functions. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Diffie-Hellman-Merkle (DHM) key exchange is defined in + * RFC-2631: Diffie-Hellman Key Agreement Method and + * Public-Key Cryptography Standards (PKCS) #3: Diffie + * Hellman Key Agreement Standard. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,17 +59,23 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_DHM_H #define MBEDTLS_DHM_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif #include "bignum.h" /* * DHM Error codes */ -#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters. */ #define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ #define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ #define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ @@ -36,167 +83,106 @@ #define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ #define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ #define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ -#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */ -/** - * RFC 3526 defines a number of standardized Diffie-Hellman groups - * for IKE. - * RFC 5114 defines a number of standardized Diffie-Hellman groups - * that can be used. - * - * Some are included here for convenience. - * - * Included are: - * RFC 3526 3. 2048-bit MODP Group - * RFC 3526 4. 3072-bit MODP Group - * RFC 3526 5. 4096-bit MODP Group - * RFC 5114 2.2. 2048-bit MODP Group with 224-bit Prime Order Subgroup - */ -#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AACAA68FFFFFFFFFFFFFFFF" +/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ -#define MBEDTLS_DHM_RFC3526_MODP_2048_G "02" - -#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ - "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" - -#define MBEDTLS_DHM_RFC3526_MODP_3072_G "02" - -#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ - "FFFFFFFFFFFFFFFF" - -#define MBEDTLS_DHM_RFC3526_MODP_4096_G "02" - -#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ - "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ - "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ - "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ - "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ - "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ - "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ - "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ - "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ - "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ - "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ - "CF9DE5384E71B81C0AC4DFFE0C10E64F" - -#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ - "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"\ - "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"\ - "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"\ - "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"\ - "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"\ - "F180EB34118E98D119529A45D6F834566E3025E316A330EF"\ - "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"\ - "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"\ - "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"\ - "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"\ - "81BC087F2A7065B384B890D3191F2BFA" +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_DHM_ALT) + /** - * \brief DHM context structure + * \brief The DHM context structure. */ -typedef struct +typedef struct mbedtls_dhm_context { - size_t len; /*!< size(P) in chars */ - mbedtls_mpi P; /*!< prime modulus */ - mbedtls_mpi G; /*!< generator */ - mbedtls_mpi X; /*!< secret value */ - mbedtls_mpi GX; /*!< self = G^X mod P */ - mbedtls_mpi GY; /*!< peer = G^Y mod P */ - mbedtls_mpi K; /*!< key = GY^X mod P */ - mbedtls_mpi RP; /*!< cached R^2 mod P */ - mbedtls_mpi Vi; /*!< blinding value */ - mbedtls_mpi Vf; /*!< un-blinding value */ - mbedtls_mpi pX; /*!< previous X */ + size_t len; /*!< The size of \p P in Bytes. */ + mbedtls_mpi P; /*!< The prime modulus. */ + mbedtls_mpi G; /*!< The generator. */ + mbedtls_mpi X; /*!< Our secret value. */ + mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi Vi; /*!< The blinding value. */ + mbedtls_mpi Vf; /*!< The unblinding value. */ + mbedtls_mpi pX; /*!< The previous \c X. */ } mbedtls_dhm_context; +#else /* MBEDTLS_DHM_ALT */ +#include "dhm_alt.h" +#endif /* MBEDTLS_DHM_ALT */ + /** - * \brief Initialize DHM context + * \brief This function initializes the DHM context. * - * \param ctx DHM context to be initialized + * \param ctx The DHM context to initialize. */ void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); /** - * \brief Parse the ServerKeyExchange parameters + * \brief This function parses the DHM parameters in a + * TLS ServerKeyExchange handshake message + * (DHM modulus, generator, and public key). * - * \param ctx DHM context - * \param p &(start of input buffer) - * \param end end of buffer + * \note In a TLS handshake, this is the how the client + * sets up its DHM context from the server's public + * DHM key material. * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + * \param ctx The DHM context to use. This must be initialized. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, - unsigned char **p, - const unsigned char *end ); + unsigned char **p, + const unsigned char *end ); /** - * \brief Setup and write the ServerKeyExchange parameters + * \brief This function generates a DHM key pair and exports its + * public part together with the DHM parameters in the format + * used in a TLS ServerKeyExchange handshake message. * - * \param ctx DHM context - * \param x_size private value size in bytes - * \param output destination buffer - * \param olen number of chars written - * \param f_rng RNG function - * \param p_rng RNG parameter + * \note This function assumes that the DHM parameters \c ctx->P + * and \c ctx->G have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). * - * \note This function assumes that ctx->P and ctx->G - * have already been properly set (for example - * using mbedtls_mpi_read_string or mbedtls_mpi_read_binary). + * \note In a TLS handshake, this is the how the server generates + * and exports its DHM key material. * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + * \param ctx The DHM context to use. This must be initialized + * and have the DHM parameters set. It may or may not + * already have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param olen The address at which to store the number of Bytes + * written on success. This must not be \c NULL. + * \param output The destination buffer. This must be a writable buffer of + * sufficient size to hold the reduced binary presentation of + * the modulus, the generator and the public key, each wrapped + * with a 2-byte length field. It is the responsibility of the + * caller to ensure that enough space is available. Refer to + * mbedtls_mpi_size() to computing the byte-size of an MPI. + * \param f_rng The RNG function. Must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t *olen, @@ -204,28 +190,66 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, void *p_rng ); /** - * \brief Import the peer's public value G^Y + * \brief This function sets the prime modulus and generator. * - * \param ctx DHM context - * \param input input buffer - * \param ilen size of buffer + * \note This function can be used to set \c ctx->P, \c ctx->G + * in preparation for mbedtls_dhm_make_params(). * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + * \param ctx The DHM context to configure. This must be initialized. + * \param P The MPI holding the DHM prime modulus. This must be + * an initialized MPI. + * \param G The MPI holding the DHM generator. This must be an + * initialized MPI. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the raw public value of the peer. + * + * \note In a TLS handshake, this is the how the server imports + * the Client's public DHM key. + * + * \param ctx The DHM context to use. This must be initialized and have + * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). + * It may or may not already have generated its own private key. + * \param input The input buffer containing the \c G^Y value of the peer. + * This must be a readable buffer of size \p ilen Bytes. + * \param ilen The size of the input buffer \p input in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen ); /** - * \brief Create own private value X and export G^X + * \brief This function creates a DHM key pair and exports + * the raw public key in big-endian format. * - * \param ctx DHM context - * \param x_size private value size in bytes - * \param output destination buffer - * \param olen must be at least equal to the size of P, ctx->len - * \param f_rng RNG function - * \param p_rng RNG parameter + * \note The destination buffer is always fully written + * so as to contain a big-endian representation of G^X mod P. + * If it is larger than \c ctx->len, it is padded accordingly + * with zero-bytes at the beginning. * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + * \param ctx The DHM context to use. This must be initialized and + * have the DHM parameters set. It may or may not already + * have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param output The destination buffer. This must be a writable buffer of + * size \p olen Bytes. + * \param olen The length of the destination buffer. This must be at least + * equal to `ctx->len` (the size of \c P). + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t olen, @@ -233,22 +257,30 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, void *p_rng ); /** - * \brief Derive and export the shared secret (G^Y)^X mod P + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. * - * \param ctx DHM context - * \param output destination buffer - * \param output_size size of the destination buffer - * \param olen on exit, holds the actual number of bytes written - * \param f_rng RNG function, for blinding purposes - * \param p_rng RNG parameter + * \note If \p f_rng is not \c NULL, it is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our private key \c X is re-used, and not used + * otherwise. We recommend always passing a non-NULL + * \p f_rng argument. * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code + * \param ctx The DHM context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param output The buffer to write the generated shared key to. This + * must be a writable buffer of size \p output_size Bytes. + * \param output_size The size of the destination buffer. This must be at + * least the size of \c ctx->len (the size of \c P). + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. * - * \note If non-NULL, f_rng is used to blind the input as - * countermeasure against timing attacks. Blinding is - * automatically used if and only if our secret value X is - * re-used and costs nothing otherwise, so it is recommended - * to always pass a non-NULL f_rng argument. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, unsigned char *output, size_t output_size, size_t *olen, @@ -256,50 +288,809 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, void *p_rng ); /** - * \brief Free and clear the components of a DHM key + * \brief This function frees and clears the components + * of a DHM context. * - * \param ctx DHM context to free and clear + * \param ctx The DHM context to free and clear. This may be \c NULL, + * in which case this function is a no-op. If it is not \c NULL, + * it must point to an initialized DHM context. */ void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); #if defined(MBEDTLS_ASN1_PARSE_C) /** \ingroup x509_module */ /** - * \brief Parse DHM parameters in PEM or DER format + * \brief This function parses DHM parameters in PEM or DER format. * - * \param dhm DHM context to be initialized - * \param dhmin input buffer - * \param dhminlen size of the buffer - * (including the terminating null byte for PEM data) + * \param dhm The DHM context to import the DHM parameters into. + * This must be initialized. + * \param dhmin The input buffer. This must be a readable buffer of + * length \p dhminlen Bytes. + * \param dhminlen The size of the input buffer \p dhmin, including the + * terminating \c NULL Byte for PEM data. * - * \return 0 if successful, or a specific DHM or PEM error code + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error + * code on failure. */ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, - size_t dhminlen ); + size_t dhminlen ); #if defined(MBEDTLS_FS_IO) /** \ingroup x509_module */ /** - * \brief Load and parse DHM parameters + * \brief This function loads and parses DHM parameters from a file. * - * \param dhm DHM context to be initialized - * \param path filename to read the DHM Parameters from + * \param dhm The DHM context to load the parameters to. + * This must be initialized. + * \param path The filename to read the DHM parameters from. + * This must not be \c NULL. * - * \return 0 if successful, or a specific DHM or PEM error code + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX + * error code on failure. */ int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_ASN1_PARSE_C */ +#if defined(MBEDTLS_SELF_TEST) + /** - * \brief Checkup routine + * \brief The DMH checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_dhm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/** + * \warning The origin of the primes in RFC 5114 is not documented and + * their use therefore constitutes a security risk! + * + * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are + * likely to be removed in a future version of the library without + * replacement. + */ + +/** + * The hexadecimal presentation of the prime underlying the + * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined + * in RFC-5114: Additional Diffie-Hellman Groups for Use with + * IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: + * Additional Diffie-Hellman Groups for Use with IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ + "81BC087F2A7065B384B890D3191F2BFA" ) + +/** + * The hexadecimal presentation of the prime underlying the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + * + * \deprecated The hex-encoded primes from RFC 3625 are deprecated and + * superseded by the corresponding macros providing them as + * binary constants. Their hex-encoded constants are likely + * to be removed in a future version of the library. + * + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 3072-bit MODP + * Group, as defined in RFC-3072: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 3072-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + #endif /* dhm.h */ diff --git a/Externals/mbedtls/include/mbedtls/ecdh.h b/Externals/mbedtls/include/mbedtls/ecdh.h index 625a281923..4479a1d46f 100644 --- a/Externals/mbedtls/include/mbedtls/ecdh.h +++ b/Externals/mbedtls/include/mbedtls/ecdh.h @@ -1,9 +1,19 @@ /** * \file ecdh.h * - * \brief Elliptic curve Diffie-Hellman + * \brief This file contains ECDH definitions and functions. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous + * key agreement protocol allowing two parties to establish a shared + * secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,77 +28,185 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_ECDH_H #define MBEDTLS_ECDH_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ecp.h" +/* + * Use a backward compatible ECDH context. + * + * This flag is always enabled for now and future versions might add a + * configuration option that conditionally undefines this flag. + * The configuration option in question may have a different name. + * + * Features undefining this flag, must have a warning in their description in + * config.h stating that the feature breaks backward compatibility. + */ +#define MBEDTLS_ECDH_LEGACY_CONTEXT + #ifdef __cplusplus extern "C" { #endif /** - * When importing from an EC key, select if it is our key or the peer's key + * Defines the source of the imported EC key. */ typedef enum { - MBEDTLS_ECDH_OURS, - MBEDTLS_ECDH_THEIRS, + MBEDTLS_ECDH_OURS, /**< Our key. */ + MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ } mbedtls_ecdh_side; +#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) /** - * \brief ECDH context structure + * Defines the ECDH implementation used. + * + * Later versions of the library may add new variants, therefore users should + * not make any assumptions about them. */ -typedef struct +typedef enum { - mbedtls_ecp_group grp; /*!< elliptic curve used */ - mbedtls_mpi d; /*!< our secret value (private key) */ - mbedtls_ecp_point Q; /*!< our public value (public key) */ - mbedtls_ecp_point Qp; /*!< peer's public value (public key) */ - mbedtls_mpi z; /*!< shared secret */ - int point_format; /*!< format for point export in TLS messages */ - mbedtls_ecp_point Vi; /*!< blinding value (for later) */ - mbedtls_ecp_point Vf; /*!< un-blinding value (for later) */ - mbedtls_mpi _d; /*!< previous d (for later) */ + MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ + MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ +} mbedtls_ecdh_variant; + +/** + * The context used by the default ECDH implementation. + * + * Later versions might change the structure of this context, therefore users + * should not make any assumptions about the structure of + * mbedtls_ecdh_context_mbed. + */ +typedef struct mbedtls_ecdh_context_mbed +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif +} mbedtls_ecdh_context_mbed; +#endif + +/** + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + * \brief The ECDH context structure. + */ +typedef struct mbedtls_ecdh_context +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ + int point_format; /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point Vi; /*!< The blinding value. */ + mbedtls_ecp_point Vf; /*!< The unblinding value. */ + mbedtls_mpi _d; /*!< The previous \p d. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + int restart_enabled; /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t point_format; /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */ + mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */ + union + { + mbedtls_ecdh_context_mbed mbed_ecdh; + } ctx; /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ } mbedtls_ecdh_context; /** - * \brief Generate a public key. - * Raw function that only does the core computation. + * \brief This function generates an ECDH keypair on an elliptic + * curve. * - * \param grp ECP group - * \param d Destination MPI (secret exponent, aka private key) - * \param Q Destination point (public key) - * \param f_rng RNG function - * \param p_rng RNG parameter + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \see ecp.h + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param d The destination MPI (private key). + * This must be initialized. + * \param Q The destination point (public key). + * This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** - * \brief Compute shared secret - * Raw function that only does the core computation. + * \brief This function computes the shared secret. * - * \param grp ECP group - * \param z Destination MPI (shared secret) - * \param Q Public key from other party - * \param d Our secret exponent (private key) - * \param f_rng RNG function (see notes) - * \param p_rng RNG parameter + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \see ecp.h * - * \note If f_rng is not NULL, it is used to implement - * countermeasures against potential elaborate timing - * attacks, see \c mbedtls_ecp_mul() for details. + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param z The destination MPI (shared secret). + * This must be initialized. + * \param Q The public key from another party. + * This must be initialized. + * \param d Our secret exponent (private key). + * This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results during the ECP computations is + * not needed (discouraged). See the documentation of + * mbedtls_ecp_mul() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a + * context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, @@ -96,34 +214,64 @@ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, void *p_rng ); /** - * \brief Initialize context + * \brief This function initializes an ECDH context. * - * \param ctx Context to initialize + * \param ctx The ECDH context to initialize. This must not be \c NULL. */ void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); /** - * \brief Free context + * \brief This function sets up the ECDH context with the information + * given. * - * \param ctx Context to free + * This function should be called after mbedtls_ecdh_init() but + * before mbedtls_ecdh_make_params(). There is no need to call + * this function before mbedtls_ecdh_read_params(). + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param grp_id The group id of the group to set up the context for. + * + * \return \c 0 on success. + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. This may be \c NULL, in which + * case this function does nothing. If it is not \c NULL, + * it must point to an initialized ECDH context. */ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); /** - * \brief Generate a public key and a TLS ServerKeyExchange payload. - * (First function used by a TLS server for ECDHE.) + * \brief This function generates an EC key pair and exports its + * in the format used in a TLS ServerKeyExchange handshake + * message. * - * \param ctx ECDH context - * \param olen number of chars written - * \param buf destination buffer - * \param blen length of buffer - * \param f_rng RNG function - * \param p_rng RNG parameter + * This is the second function used by a TLS server for ECDHE + * ciphersuites. (It is called after mbedtls_ecdh_setup().) * - * \note This function assumes that ctx->grp has already been - * properly set (for example using mbedtls_ecp_group_load). + * \see ecp.h * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param olen The address at which to store the number of Bytes written. + * \param buf The destination buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -131,45 +279,81 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng ); /** - * \brief Parse and procress a TLS ServerKeyExhange payload. - * (First function used by a TLS client for ECDHE.) + * \brief This function parses the ECDHE parameters in a + * TLS ServerKeyExchange handshake message. * - * \param ctx ECDH context - * \param buf pointer to start of input buffer - * \param end one past end of buffer + * \note In a TLS handshake, this is the how the client + * sets up its ECDHE context from the server's public + * ECDHE key material. + * + * \see ecp.h + * + * \param ctx The ECDHE context to use. This must be initialized. + * \param buf On input, \c *buf must be the start of the input buffer. + * On output, \c *buf is updated to point to the end of the + * data that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code */ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, - const unsigned char **buf, const unsigned char *end ); + const unsigned char **buf, + const unsigned char *end ); /** - * \brief Setup an ECDH context from an EC key. - * (Used by clients and servers in place of the - * ServerKeyEchange for static ECDH: import ECDH parameters - * from a certificate's EC key information.) + * \brief This function sets up an ECDH context from an EC key. * - * \param ctx ECDH constext to set - * \param key EC key to use - * \param side Is it our key (1) or the peer's key (0) ? + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \see ecp.h + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param key The EC key to use. This must be initialized. + * \param side Defines the source of the key. Possible values are: + * - #MBEDTLS_ECDH_OURS: The key is ours. + * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code */ -int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, - mbedtls_ecdh_side side ); +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); /** - * \brief Generate a public key and a TLS ClientKeyExchange payload. - * (Second function used by a TLS client for ECDH(E).) + * \brief This function generates a public key and exports it + * as a TLS ClientKeyExchange payload. * - * \param ctx ECDH context - * \param olen number of bytes actually written - * \param buf destination buffer - * \param blen size of destination buffer - * \param f_rng RNG function - * \param p_rng RNG parameter + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, the latter usually by + * mbedtls_ecdh_read_params(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The destination buffer. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The size of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -177,36 +361,78 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng ); /** - * \brief Parse and process a TLS ClientKeyExchange payload. - * (Second function used by a TLS server for ECDH(E).) + * \brief This function parses and processes the ECDHE payload of a + * TLS ClientKeyExchange message. * - * \param ctx ECDH context - * \param buf start of input buffer - * \param blen length of input buffer + * This is the third function used by a TLS server for ECDH(E) + * ciphersuites. (It is called after mbedtls_ecdh_setup() and + * mbedtls_ecdh_make_params().) * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param buf The pointer to the ClientKeyExchange payload. This must + * be a readable buffer of length \p blen Bytes. + * \param blen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, - const unsigned char *buf, size_t blen ); + const unsigned char *buf, size_t blen ); /** - * \brief Derive and export the shared secret. - * (Last function used by both TLS client en servers.) + * \brief This function derives and exports the shared secret. * - * \param ctx ECDH context - * \param olen number of bytes written - * \param buf destination buffer - * \param blen buffer length - * \param f_rng RNG function, see notes for \c mbedtls_ecdh_compute_shared() - * \param p_rng RNG parameter + * This is the last function used by both TLS client + * and servers. * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \see ecp.h + + * \param ctx The ECDH context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param olen The address at which to store the total number of + * Bytes written on success. This must not be \c NULL. + * \param buf The buffer to write the generated shared key to. This + * must be a writable buffer of size \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief This function enables restartable EC computations for this + * context. (Default: disabled.) + * + * \see \c mbedtls_ecp_set_max_ops() + * + * \note It is not possible to safely disable restartable + * computations once enabled, except by free-ing the context, + * which cancels possible in-progress operations. + * + * \param ctx The ECDH context to use. This must be initialized. + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/ecdsa.h b/Externals/mbedtls/include/mbedtls/ecdsa.h index 52827d8d1a..f8b28507c2 100644 --- a/Externals/mbedtls/include/mbedtls/ecdsa.h +++ b/Externals/mbedtls/include/mbedtls/ecdsa.h @@ -1,9 +1,17 @@ /** * \file ecdsa.h * - * \brief Elliptic curve DSA + * \brief This file contains ECDSA definitions and functions. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in + * Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,16 +26,23 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_ECDSA_H #define MBEDTLS_ECDSA_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ecp.h" #include "md.h" /* - * RFC 4492 page 20: + * RFC-4492 page 20: * * Ecdsa-Sig-Value ::= SEQUENCE { * r INTEGER, @@ -43,34 +58,103 @@ #if MBEDTLS_ECP_MAX_BYTES > 124 #error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" #endif -/** Maximum size of an ECDSA signature in bytes */ +/** The maximal size of an ECDSA signature in Bytes. */ #define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) -/** - * \brief ECDSA context structure - */ -typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; - #ifdef __cplusplus extern "C" { #endif /** - * \brief Compute ECDSA signature of a previously hashed message + * \brief The ECDSA context structure. * - * \note The deterministic version is usually prefered. + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for ecdsa_verify() * - * \param grp ECP group - * \param r First output integer - * \param s Second output integer - * \param d Private signing key - * \param buf Message hash - * \param blen Length of buf - * \param f_rng RNG function - * \param p_rng RNG parameter + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; + +/** + * \brief Internal restart context for ecdsa_sign() * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Internal restart context for ecdsa_sign_det() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; +#endif + +/** + * \brief General context for resuming ECDSA operations + */ +typedef struct +{ + mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ +#endif +} mbedtls_ecdsa_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_ecdsa_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det() is usually preferred. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized. + * \param buf The content to be signed. This is usually the hash of + * the original data to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, @@ -78,74 +162,184 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /** - * \brief Compute ECDSA signature of a previously hashed message, - * deterministic version (RFC 6979). + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. * - * \param grp ECP group - * \param r First output integer - * \param s Second output integer - * \param d Private signing key - * \param buf Message hash - * \param blen Length of buf - * \param md_alg MD algorithm used to hash the message + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ); +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ); #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ /** - * \brief Verify ECDSA signature of a previously hashed message + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. * - * \param grp ECP group - * \param buf Message hash - * \param blen Length of buf - * \param Q Public key to use for verification - * \param r First integer of the signature - * \param s Second integer of the signature + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \see ecp.h + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param buf The hashed content that was signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param Q The public key to use for verification. This must be + * initialized and setup. + * \param r The first integer of the signature. + * This must be initialized. + * \param s The second integer of the signature. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature + * is invalid. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. */ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, + const mbedtls_mpi *s); /** - * \brief Compute ECDSA signature and write it to buffer, - * serialized as defined in RFC 4492 page 20. - * (Not thread-safe to use same context in multiple threads) + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). * - * \note The deterministice version (RFC 6979) is used if - * MBEDTLS_ECDSA_DETERMINISTIC is defined. + * \warning It is not thread-safe to use the same context in + * multiple threads. * - * \param ctx ECDSA context - * \param md_alg Algorithm that was used to hash the message - * \param hash Message hash - * \param hlen Length of hash - * \param sig Buffer that will hold the signature - * \param slen Length of the signature written - * \param f_rng RNG function - * \param p_rng RNG parameter + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). * - * \note The "sig" buffer must be at least as large as twice the - * size of the curve used, plus 9 (eg. 73 bytes if a 256-bit - * curve is used). MBEDTLS_ECDSA_MAX_LEN is always safe. + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX, MBEDTLS_ERR_MPI_XXX or - * MBEDTLS_ERR_ASN1_XXX error code + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, in a restartable way. + * + * \see \c mbedtls_ecdsa_write_signature() + * + * \note This function is like \c mbedtls_ecdsa_write_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) @@ -154,27 +348,47 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t #define MBEDTLS_DEPRECATED #endif /** - * \brief Compute ECDSA signature and write it to buffer, - * serialized as defined in RFC 4492 page 20. - * Deterministic version, RFC 6979. - * (Not thread-safe to use same context in multiple threads) + * \brief This function computes an ECDSA signature and writes + * it to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). * - * \deprecated Superseded by mbedtls_ecdsa_write_signature() in 2.0.0 + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) + * and Elliptic Curve Digital Signature Algorithm (ECDSA). * - * \param ctx ECDSA context - * \param hash Message hash - * \param hlen Length of hash - * \param sig Buffer that will hold the signature - * \param slen Length of the signature written - * \param md_alg MD algorithm used to hash the message + * \warning It is not thread-safe to use the same context in + * multiple threads. * - * \note The "sig" buffer must be at least as large as twice the - * size of the curve used, plus 9 (eg. 73 bytes if a 256-bit - * curve is used). MBEDTLS_ECDSA_MAX_LEN is always safe. + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX, MBEDTLS_ERR_MPI_XXX or - * MBEDTLS_ERR_ASN1_XXX error code + * \see ecp.h + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in + * Mbed TLS version 2.0 and later. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param md_alg The message digest that was used to hash the message. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, @@ -185,62 +399,145 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ /** - * \brief Read and verify an ECDSA signature + * \brief This function reads and verifies an ECDSA signature. * - * \param ctx ECDSA context - * \param hash Message hash - * \param hlen Size of hash - * \param sig Signature to read and verify - * \param slen Size of sig + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, - * MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than siglen, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX error code + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. */ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen ); /** - * \brief Generate an ECDSA keypair on the given curve + * \brief This function reads and verifies an ECDSA signature, + * in a restartable way. * - * \param ctx ECDSA context in which the keypair should be stored - * \param gid Group (elliptic curve) to use. One of the various - * MBEDTLS_ECP_DP_XXX macros depending on configuration. - * \param f_rng RNG function - * \param p_rng RNG parameter + * \see \c mbedtls_ecdsa_read_signature() * - * \return 0 on success, or a MBEDTLS_ERR_ECP_XXX code. + * \note This function is like \c mbedtls_ecdsa_read_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \see ecp.h + * + * \param ctx The ECDSA context to store the keypair in. + * This must be initialized. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** - * \brief Set an ECDSA context from an EC key pair + * \brief This function sets up an ECDSA context from an EC key pair. * - * \param ctx ECDSA context to set - * \param key EC key to use + * \see ecp.h * - * \return 0 on success, or a MBEDTLS_ERR_ECP_XXX code. + * \param ctx The ECDSA context to setup. This must be initialized. + * \param key The EC key to use. This must be initialized and hold + * a private-public key pair or a public key. In the former + * case, the ECDSA context may be used for signature creation + * and verification after this call. In the latter case, it + * may be used for signature verification. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ -int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, + const mbedtls_ecp_keypair *key ); /** - * \brief Initialize context + * \brief This function initializes an ECDSA context. * - * \param ctx Context to initialize + * \param ctx The ECDSA context to initialize. + * This must not be \c NULL. */ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); /** - * \brief Free context + * \brief This function frees an ECDSA context. * - * \param ctx Context to free + * \param ctx The ECDSA context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. */ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/ecjpake.h b/Externals/mbedtls/include/mbedtls/ecjpake.h index b7b61604d0..3d8d02ae64 100644 --- a/Externals/mbedtls/include/mbedtls/ecjpake.h +++ b/Externals/mbedtls/include/mbedtls/ecjpake.h @@ -2,7 +2,8 @@ * \file ecjpake.h * * \brief Elliptic curve J-PAKE - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -39,6 +40,11 @@ * The payloads are serialized in a way suitable for use in TLS, but could * also be use outside TLS. */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif #include "ecp.h" #include "md.h" @@ -55,6 +61,7 @@ typedef enum { MBEDTLS_ECJPAKE_SERVER, /**< Server */ } mbedtls_ecjpake_role; +#if !defined(MBEDTLS_ECJPAKE_ALT) /** * EC J-PAKE context structure. * @@ -66,7 +73,7 @@ typedef enum { * convetion from the Thread v1.0 spec. Correspondance is indicated in the * description as a pair C: client name, S: server name */ -typedef struct +typedef struct mbedtls_ecjpake_context { const mbedtls_md_info_t *md_info; /**< Hash to use */ mbedtls_ecp_group grp; /**< Elliptic curve */ @@ -85,29 +92,38 @@ typedef struct mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ } mbedtls_ecjpake_context; +#else /* MBEDTLS_ECJPAKE_ALT */ +#include "ecjpake_alt.h" +#endif /* MBEDTLS_ECJPAKE_ALT */ + /** - * \brief Initialize a context - * (just makes it ready for setup() or free()). + * \brief Initialize an ECJPAKE context. * - * \param ctx context to initialize + * \param ctx The ECJPAKE context to initialize. + * This must not be \c NULL. */ void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); /** - * \brief Set up a context for use + * \brief Set up an ECJPAKE context for use. * * \note Currently the only values for hash/curve allowed by the - * standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1. + * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. * - * \param ctx context to set up - * \param role Our role: client or server - * \param hash hash function to use (MBEDTLS_MD_XXX) - * \param curve elliptic curve identifier (MBEDTLS_ECP_DP_XXX) - * \param secret pre-shared secret (passphrase) - * \param len length of the shared secret + * \param ctx The ECJPAKE context to set up. This must be initialized. + * \param role The role of the caller. This must be either + * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. + * \param hash The identifier of the hash function to use, + * for example #MBEDTLS_MD_SHA256. + * \param curve The identifier of the elliptic curve to use, + * for example #MBEDTLS_ECP_DP_SECP256R1. + * \param secret The pre-shared secret (passphrase). This must be + * a readable buffer of length \p len Bytes. It need + * only be valid for the duration of this call. + * \param len The length of the pre-shared secret \p secret. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, mbedtls_ecjpake_role role, @@ -116,30 +132,35 @@ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, const unsigned char *secret, size_t len ); -/* - * \brief Check if a context is ready for use +/** + * \brief Check if an ECJPAKE context is ready for use. * - * \param ctx Context to check + * \param ctx The ECJPAKE context to check. This must be + * initialized. * - * \return 0 if the context is ready for use, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + * \return \c 0 if the context is ready for use. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. */ int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); /** * \brief Generate and write the first round message * (TLS: contents of the Client/ServerHello extension, - * excluding extension type and length bytes) + * excluding extension type and length bytes). * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param ctx The ECJPAKE context to use. This must be + * initialized and set up. + * \param buf The buffer to write the contents to. This must be a + * writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number + * of Bytes written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, @@ -149,14 +170,16 @@ int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, /** * \brief Read and process the first round message * (TLS: contents of the Client/ServerHello extension, - * excluding extension type and length bytes) + * excluding extension type and length bytes). * - * \param ctx Context to use - * \param buf Pointer to extension contents - * \param len Extension length + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up. + * \param buf The buffer holding the first round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, const unsigned char *buf, @@ -164,17 +187,21 @@ int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, /** * \brief Generate and write the second round message - * (TLS: contents of the Client/ServerKeyExchange) + * (TLS: contents of the Client/ServerKeyExchange). * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up, and already have performed round one. + * \param buf The buffer to write the round two contents to. + * This must be a writable buffer of length \p len Bytes. + * \param len The size of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, @@ -183,14 +210,16 @@ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, /** * \brief Read and process the second round message - * (TLS: contents of the Client/ServerKeyExchange) + * (TLS: contents of the Client/ServerKeyExchange). * - * \param ctx Context to use - * \param buf Pointer to the message - * \param len Message length + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up and already have performed round one. + * \param buf The buffer holding the second round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, const unsigned char *buf, @@ -198,17 +227,21 @@ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, /** * \brief Derive the shared secret - * (TLS: Pre-Master Secret) + * (TLS: Pre-Master Secret). * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up and have performed both round one and two. + * \param buf The buffer to write the derived secret to. This must + * be a writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. * - * \return 0 if successfull, - * a negative error code otherwise + * \return \c 0 if successful. + * \return A negative error code on failure. */ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, @@ -216,23 +249,29 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, void *p_rng ); /** - * \brief Free a context's content + * \brief This clears an ECJPAKE context and frees any + * embedded data structure. * - * \param ctx context to free + * \param ctx The ECJPAKE context to free. This may be \c NULL, + * in which case this function does nothing. If it is not + * \c NULL, it must point to an initialized ECJPAKE context. */ void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); #if defined(MBEDTLS_SELF_TEST) + /** * \brief Checkup routine * * \return 0 if successful, or 1 if a test failed */ int mbedtls_ecjpake_self_test( int verbose ); -#endif + +#endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif + #endif /* ecjpake.h */ diff --git a/Externals/mbedtls/include/mbedtls/ecp.h b/Externals/mbedtls/include/mbedtls/ecp.h index 5246c789d3..24017780d4 100644 --- a/Externals/mbedtls/include/mbedtls/ecp.h +++ b/Externals/mbedtls/include/mbedtls/ecp.h @@ -1,9 +1,21 @@ /** * \file ecp.h * - * \brief Elliptic curves over GF(p) + * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The use of ECP in cryptography and TLS is defined in + * Standards for Efficient Cryptography Group (SECG): SEC1 + * Elliptic Curve Cryptography and + * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites + * for Transport Layer Security (TLS). + * + * RFC-2409: The Internet Key Exchange (IKE) defines ECP + * group types. + * + */ + +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,11 +30,18 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_ECP_H #define MBEDTLS_ECP_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "bignum.h" /* @@ -30,150 +49,165 @@ */ #define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ -#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< The requested feature is not available, for example, the requested curve is not supported. */ #define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ #define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ -#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ -#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ + +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */ #ifdef __cplusplus extern "C" { #endif /** - * Domain parameters (curve, subgroup and generator) identifiers. + * Domain-parameter identifiers: curve, subgroup, and generator. * - * Only curves over prime fields are supported. + * \note Only curves over prime fields are supported. * * \warning This library does not support validation of arbitrary domain - * parameters. Therefore, only well-known domain parameters from trusted + * parameters. Therefore, only standardized domain parameters from trusted * sources should be used. See mbedtls_ecp_group_load(). */ typedef enum { - MBEDTLS_ECP_DP_NONE = 0, - MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ - MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ - MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ - MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ - MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ - MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ - MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ - MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ - MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ - MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ - MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ - MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ + MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ + MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ + MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ } mbedtls_ecp_group_id; /** - * Number of supported curves (plus one for NONE). + * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. * - * (Montgomery curves excluded for now.) + * \note Montgomery curves are currently excluded. */ #define MBEDTLS_ECP_DP_MAX 12 /** - * Curve information for use by other modules + * Curve information, for use by other modules. */ -typedef struct +typedef struct mbedtls_ecp_curve_info { - mbedtls_ecp_group_id grp_id; /*!< Internal identifier */ - uint16_t tls_id; /*!< TLS NamedCurve identifier */ - uint16_t bit_size; /*!< Curve size in bits */ - const char *name; /*!< Human-friendly name */ + mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ + uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ + uint16_t bit_size; /*!< The curve size in bits. */ + const char *name; /*!< A human-friendly name. */ } mbedtls_ecp_curve_info; /** - * \brief ECP point structure (jacobian coordinates) + * \brief The ECP point structure, in Jacobian coordinates. * * \note All functions expect and return points satisfying - * the following condition: Z == 0 or Z == 1. (Other - * values of Z are used by internal functions only.) - * The point is zero, or "at infinity", if Z == 0. - * Otherwise, X and Y are its standard (affine) coordinates. + * the following condition: Z == 0 or + * Z == 1. Other values of \p Z are + * used only by internal functions. + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, \p X and \p Y are its standard (affine) + * coordinates. */ -typedef struct +typedef struct mbedtls_ecp_point { - mbedtls_mpi X; /*!< the point's X coordinate */ - mbedtls_mpi Y; /*!< the point's Y coordinate */ - mbedtls_mpi Z; /*!< the point's Z coordinate */ + mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ + mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */ } mbedtls_ecp_point; -/** - * \brief ECP group structure +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation * - * We consider two types of curves equations: - * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) - * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) - * In both cases, a generator G for a prime-order subgroup is fixed. In the - * short weierstrass, this subgroup is actually the whole curve, and its - * cardinal is denoted by N. - * - * In the case of Short Weierstrass curves, our code requires that N is an odd - * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.) - * - * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is - * the quantity actually used in the formulas. Also, nbits is not the size of N - * but the required size for private keys. - * - * If modp is NULL, reduction modulo P is done using a generic algorithm. - * Otherwise, it must point to a function that takes an mbedtls_mpi in the range - * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more - * than pbits, so that the integer may be efficiently brought in the 0..P-1 - * range by a few additions or substractions. It must return 0 on success and - * non-zero on failure. + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) */ -typedef struct -{ - mbedtls_ecp_group_id id; /*!< internal group identifier */ - mbedtls_mpi P; /*!< prime modulus of the base field */ - mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ - mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */ - mbedtls_ecp_point G; /*!< generator of the (sub)group used */ - mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */ - size_t pbits; /*!< number of bits in P */ - size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ - unsigned int h; /*!< internal: 1 if the constants are static */ - int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */ - int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */ - int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */ - void *t_data; /*!< unused */ - mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ - size_t T_size; /*!< number for pre-computed points */ -} -mbedtls_ecp_group; /** - * \brief ECP key pair structure + * \brief The ECP group structure. * - * A generic key pair that could be used for ECDSA, fixed ECDH, etc. + * We consider two types of curve equations: + *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P + * (SEC1 + RFC-4492)
  • + *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, + * Curve448)
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed. + * + * For Short Weierstrass, this subgroup is the whole curve, and its + * cardinality is denoted by \p N. Our code requires that \p N is an + * odd prime as mbedtls_ecp_mul() requires an odd number, and + * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. + * + * For Montgomery curves, we do not store \p A, but (A + 2) / 4, + * which is the quantity used in the formulas. Additionally, \p nbits is + * not the size of \p N but the required size for private keys. + * + * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. + * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the + * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer + * which is congruent mod \p P to the given MPI, and is close enough to \p pbits + * in size, so that it may be efficiently brought in the 0..P-1 range by a few + * additions or subtractions. Therefore, it is only an approximative modular + * reduction. It must return 0 on success and non-zero on failure. + * + * \note Alternative implementations must keep the group IDs distinct. If + * two group structures have the same ID, then they must be + * identical. * - * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. */ -typedef struct +typedef struct mbedtls_ecp_group { - mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ - mbedtls_mpi d; /*!< our secret value */ - mbedtls_ecp_point Q; /*!< our public value */ + mbedtls_ecp_group_id id; /*!< An internal group identifier. */ + mbedtls_mpi P; /*!< The prime modulus of the base field. */ + mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For + Montgomery curves: (A + 2) / 4. */ + mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. + For Montgomery curves: unused. */ + mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ + mbedtls_mpi N; /*!< The order of \p G. */ + size_t pbits; /*!< The number of bits in \p P.*/ + size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. + For Montgomery curves: the number of bits in the + private keys. */ + unsigned int h; /*!< \internal 1 if the constants are static. */ + int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *t_data; /*!< Unused. */ + mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */ + size_t T_size; /*!< The number of pre-computed points. */ } -mbedtls_ecp_keypair; +mbedtls_ecp_group; /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. + * Either change them in config.h, or define them using the compiler command line. * \{ */ #if !defined(MBEDTLS_ECP_MAX_BITS) /** - * Maximum size of the groups (that is, of N and P) + * The maximum size of the groups, that is, of \c N and \c P. */ -#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< The maximum size of groups, in bits. */ #endif #define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) @@ -196,11 +230,10 @@ mbedtls_ecp_keypair; * 521 145 141 135 120 97 * 384 214 209 198 177 146 * 256 320 320 303 262 226 - * 224 475 475 453 398 342 * 192 640 640 633 587 476 */ -#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< The maximum window size used. */ #endif /* MBEDTLS_ECP_WINDOW_SIZE */ #if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) @@ -215,33 +248,188 @@ mbedtls_ecp_keypair; * * Change this value to 0 to reduce peak memory usage. */ -#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ #endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ /* \} name SECTION: Module settings */ +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for multiplication + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; + +/** + * \brief Internal restart context for ecp_muladd() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; + +/** + * \brief General context for resuming ECC operations + */ +typedef struct +{ + unsigned ops_done; /*!< current ops count */ + unsigned depth; /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ +} mbedtls_ecp_restart_ctx; + +/* + * Operation counts for restartable functions + */ +#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ +#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ +#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ +#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ + +/** + * \brief Internal; for restartable functions in other modules. + * Check and update basic ops budget. + * + * \param grp Group structure + * \param rs_ctx Restart context + * \param ops Number of basic ops to do + * + * \return \c 0 if doing \p ops basic ops is still allowed, + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ); + +/* Utility macro for checking and updating ops budget */ +#define MBEDTLS_ECP_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \ + (unsigned) (ops) ) ); + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */ + +/* We want to declare restartable versions of existing functions anyway */ +typedef void mbedtls_ecp_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief The ECP key-pair structure. + * + * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. + * + * \note Members are deliberately in the same order as in the + * ::mbedtls_ecdsa_context structure. + */ +typedef struct mbedtls_ecp_keypair +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + /* * Point formats, from RFC 4492's enum ECPointFormat */ -#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ -#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ /* * Some other constants from RFC 4492 */ -#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Set the maximum number of basic operations done in a row. + * + * If more operations are needed to complete a computation, + * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * function performing the computation. It is then the + * caller's responsibility to either call again with the same + * parameters until it returns 0 or an error code; or to free + * the restart context if the operation is to be aborted. + * + * It is strictly required that all input parameters and the + * restart context be the same on successive calls for the + * same operation, but output parameters need not be the + * same; they must not be used until the function finally + * returns 0. + * + * This only applies to functions whose documentation + * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the + * SSL module). For functions that accept a "restart context" + * argument, passing NULL disables restart and makes the + * function equivalent to the function with the same name + * with \c _restartable removed. For functions in the ECDH + * module, restart is disabled unless the function accepts + * an "ECDH context" argument and + * mbedtls_ecdh_enable_restart() was previously called on + * that context. For function in the SSL module, restart is + * only enabled for specific sides and key exchanges + * (currently only for clients and ECDHE-ECDSA). + * + * \param max_ops Maximum number of basic operations done in a row. + * Default: 0 (unlimited). + * Lower (non-zero) values mean ECC functions will block for + * a lesser maximum amount of time. + * + * \note A "basic operation" is defined as a rough equivalent of a + * multiplication in GF(p) for the NIST P-256 curve. + * As an indication, with default settings, a scalar + * multiplication (full run of \c mbedtls_ecp_mul()) is: + * - about 3300 basic operations for P-256 + * - about 9400 basic operations for P-384 + * + * \note Very low values are not always respected: sometimes + * functions need to block for a minimum number of + * operations, and will do so even if max_ops is set to a + * lower value. That minimum depends on the curve size, and + * can be made lower by decreasing the value of + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the + * lowest effective value for various curves and values of + * that parameter (w for short): + * w=6 w=5 w=4 w=3 w=2 + * P-256 208 208 160 136 124 + * P-384 682 416 320 272 248 + * P-521 1364 832 640 544 496 + * + * \note This setting is currently ignored by Curve25519. + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ); /** - * \brief Get the list of supported curves in order of preferrence - * (full information) + * \brief Check if restart is enabled (max_ops != 0) * - * \return A statically allocated array, the last entry is 0. + * \return \c 0 if \c max_ops == 0 (restart disabled) + * \return \c 1 otherwise (restart enabled) + */ +int mbedtls_ecp_restart_is_enabled( void ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function retrieves the information defined in + * mbedtls_ecp_curve_info() for all supported curves in order + * of preference. + * + * \return A statically allocated array. The last entry is 0. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); /** - * \brief Get the list of supported curves in order of preferrence - * (grp_id only) + * \brief This function retrieves the list of internal group + * identifiers of all supported curves in the order of + * preference. * * \return A statically allocated array, * terminated with MBEDTLS_ECP_DP_NONE. @@ -249,418 +437,693 @@ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); /** - * \brief Get curve information from an internal group identifier + * \brief This function retrieves curve information from an internal + * group identifier. * - * \param grp_id A MBEDTLS_ECP_DP_XXX value + * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. * - * \return The associated curve information or NULL + * \return The associated curve information on success. + * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); /** - * \brief Get curve information from a TLS NamedCurve value + * \brief This function retrieves curve information from a TLS + * NamedCurve value. * - * \param tls_id A MBEDTLS_ECP_DP_XXX value + * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. * - * \return The associated curve information or NULL + * \return The associated curve information on success. + * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); /** - * \brief Get curve information from a human-readable name + * \brief This function retrieves curve information from a + * human-readable name. * - * \param name The name + * \param name The human-readable name. * - * \return The associated curve information or NULL + * \return The associated curve information on success. + * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); /** - * \brief Initialize a point (as zero) + * \brief This function initializes a point as zero. + * + * \param pt The point to initialize. */ void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); /** - * \brief Initialize a group (to something meaningless) + * \brief This function initializes an ECP group context + * without loading any domain parameters. + * + * \note After this function is called, domain parameters + * for various ECP groups can be loaded through the + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group() + * functions. */ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); /** - * \brief Initialize a key pair (as an invalid one) + * \brief This function initializes a key pair as an invalid one. + * + * \param key The key pair to initialize. */ void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); /** - * \brief Free the components of a point + * \brief This function frees the components of a point. + * + * \param pt The point to free. */ void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); /** - * \brief Free the components of an ECP group + * \brief This function frees the components of an ECP group. + * + * \param grp The group to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP group. */ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); /** - * \brief Free the components of a key pair + * \brief This function frees the components of a key pair. + * + * \param key The key pair to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP key pair. */ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); +#if defined(MBEDTLS_ECP_RESTARTABLE) /** - * \brief Copy the contents of point Q into P + * \brief Initialize a restart context. * - * \param P Destination point - * \param Q Source point + * \param ctx The restart context to initialize. This must + * not be \c NULL. + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \param ctx The restart context to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized restart context. + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function copies the contents of point \p Q into + * point \p P. + * + * \param P The destination point. This must be initialized. + * \param Q The source point. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code for other kinds of failure. */ int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); /** - * \brief Copy the contents of a group object + * \brief This function copies the contents of group \p src into + * group \p dst. * - * \param dst Destination group - * \param src Source group + * \param dst The destination group. This must be initialized. + * \param src The source group. This must be initialized. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, + const mbedtls_ecp_group *src ); /** - * \brief Set a point to zero + * \brief This function sets a point to the point at infinity. * - * \param pt Destination point + * \param pt The point to set. This must be initialized. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); /** - * \brief Tell if a point is zero + * \brief This function checks if a point is the point at infinity. * - * \param pt Point to test + * \param pt The point to test. This must be initialized. * - * \return 1 if point is zero, 0 otherwise + * \return \c 1 if the point is zero. + * \return \c 0 if the point is non-zero. + * \return A negative error code on failure. */ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); /** - * \brief Compare two points + * \brief This function compares two points. * - * \note This assumes the points are normalized. Otherwise, + * \note This assumes that the points are normalized. Otherwise, * they may compare as "not equal" even if they are. * - * \param P First point to compare - * \param Q Second point to compare + * \param P The first point to compare. This must be initialized. + * \param Q The second point to compare. This must be initialized. * - * \return 0 if the points are equal, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise + * \return \c 0 if the points are equal. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. */ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); /** - * \brief Import a non-zero point from two ASCII strings + * \brief This function imports a non-zero point from two ASCII + * strings. * - * \param P Destination point - * \param radix Input numeric base - * \param x First affine coordinate as a null-terminated string - * \param y Second affine coordinate as a null-terminated string + * \param P The destination point. This must be initialized. + * \param radix The numeric base of the input. + * \param x The first affine coordinate, as a null-terminated string. + * \param y The second affine coordinate, as a null-terminated string. * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. */ int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, const char *x, const char *y ); /** - * \brief Export a point into unsigned binary data + * \brief This function exports a point into unsigned binary data. * - * \param grp Group to which the point should belong - * \param P Point to export - * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro - * \param olen Length of the actual output - * \param buf Output buffer - * \param buflen Length of the output buffer + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The point to export. This must be initialized. + * \param format The point format. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length of + * the output in Bytes. This must not be \c NULL. + * \param buf The output buffer. This must be a writable buffer + * of length \p buflen Bytes. + * \param buflen The length of the output buffer \p buf in Bytes. * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer + * is too small to hold the point. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen ); /** - * \brief Import a point from unsigned binary data + * \brief This function imports a point from unsigned binary data. * - * \param grp Group to which the point should belong - * \param P Point to import - * \param buf Input buffer - * \param ilen Actual length of input + * \note This function does not check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() + * for that. * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The destination context to import the point to. + * This must be initialized. + * \param buf The input buffer. This must be a readable buffer + * of length \p ilen Bytes. + * \param ilen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format * is not implemented. - * - * \note This function does NOT check that the point actually - * belongs to the given group, see mbedtls_ecp_check_pubkey() for - * that. */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, - const unsigned char *buf, size_t ilen ); +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); /** - * \brief Import a point from a TLS ECPoint record + * \brief This function imports a point from a TLS ECPoint record. * - * \param grp ECP group used - * \param pt Destination point - * \param buf $(Start of input buffer) - * \param len Buffer length + * \note On function return, \p *buf is updated to point immediately + * after the ECPoint record. * - * \note buf is updated to point right after the ECPoint on exit + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The destination point. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization + * failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t len ); +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); /** - * \brief Export a point as a TLS ECPoint record + * \brief This function exports a point as a TLS ECPoint record + * defined in RFC 4492, Section 5.4. * - * \param grp ECP group used - * \param pt Point to export - * \param format Export format - * \param olen length of data written - * \param buf Buffer to write to - * \param blen Buffer length + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to be exported. This must be initialized. + * \param format The point format to use. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length in Bytes + * of the data written. + * \param buf The target buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the target buffer \p buf in Bytes. * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer + * is too small to hold the exported point. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, - int format, size_t *olen, - unsigned char *buf, size_t blen ); +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); /** - * \brief Set a group using well-known domain parameters + * \brief This function sets up an ECP group context + * from a standardized set of domain parameters. * - * \param grp Destination group - * \param index Index in the list of well-known domain parameters + * \note The index should be a value of the NamedCurve enum, + * as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS), + * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups + * \param grp The group context to setup. This must be initialized. + * \param id The identifier of the domain parameter set to load. * - * \note Index should be a value of RFC 4492's enum NamedCurve, - * usually in the form of a MBEDTLS_ECP_DP_XXX macro. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id index ); +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); /** - * \brief Set a group from a TLS ECParameters record + * \brief This function sets up an ECP group context from a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. * - * \param grp Destination group - * \param buf &(Start of input buffer) - * \param len Buffer length + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. * - * \note buf is updated to point right after ECParameters on exit + * \param grp The group context to setup. This must be initialized. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ); /** - * \brief Write the TLS ECParameters record for a group + * \brief This function extracts an elliptic curve group ID from a + * TLS ECParameters record as defined in RFC 4492, Section 5.4. * - * \param grp ECP group used - * \param olen Number of bytes actually written - * \param buf Buffer to write to - * \param blen Buffer length + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL + * \param grp The address at which to store the group id. + * This must not be \c NULL. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, - unsigned char *buf, size_t blen ); +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, + size_t len ); +/** + * \brief This function exports an elliptic curve as a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to be exported. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The buffer to write to. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output + * buffer is too small to hold the exported group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, + size_t *olen, + unsigned char *buf, size_t blen ); /** - * \brief Multiplication by an integer: R = m * P - * (Not thread-safe to use same group in multiple threads) + * \brief This function performs a scalar multiplication of a point + * by an integer: \p R = \p m * \p P. * - * \note In order to prevent timing attacks, this function - * executes the exact same sequence of (base field) - * operations for any valid m. It avoids any if-branch or - * array index depending on the value of m. + * It is not thread-safe to use same group in multiple threads. * - * \note If f_rng is not NULL, it is used to randomize intermediate - * results in order to prevent potential timing attacks - * targeting these results. It is recommended to always - * provide a non-NULL f_rng (the overhead is negligible). + * \note To prevent timing attacks, this function + * executes the exact same sequence of base-field + * operations for any valid \p m. It avoids any if-branch or + * array index depending on the value of \p m. * - * \param grp ECP group - * \param R Destination point - * \param m Integer by which to multiply - * \param P Point to multiply - * \param f_rng RNG function (see notes) - * \param p_rng RNG parameter + * \note If \p f_rng is not NULL, it is used to randomize + * intermediate results to prevent potential timing attacks + * targeting these results. We recommend always providing + * a non-NULL \p f_rng. The overhead is negligible. * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey - * or P is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); /** - * \brief Multiplication and addition of two points by integers: - * R = m * P + n * Q - * (Not thread-safe to use same group in multiple threads) + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P in a restartable way. * - * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee - * a constant execution flow and timing. + * \see mbedtls_ecp_mul() * - * \param grp ECP group - * \param R Destination point - * \param m Integer by which to multiply P - * \param P Point to multiply by m - * \param n Integer by which to multiply Q - * \param Q Point to be multiplied by n + * \note This function does the same as \c mbedtls_ecp_mul(), but + * it can return early and restart according to the limit set + * with \c mbedtls_ecp_set_max_ops() to reduce blocking. * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey - * or P or Q is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q + * + * It is not thread-safe to use same group in multiple threads. + * + * \note In contrast to mbedtls_ecp_mul(), this function does not + * guarantee a constant execution flow and timing. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); /** - * \brief Check that a point is a valid public key on this curve + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q in a + * restartable way. * - * \param grp Curve/group the point should belong to - * \param pt Point to check + * \see \c mbedtls_ecp_muladd() * - * \return 0 if point is a valid public key, - * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * \note This function works the same as \c mbedtls_ecp_muladd(), + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * - * \note This function only checks the point is non-zero, has valid - * coordinates and lies on the curve, but not that it is - * indeed a multiple of G. This is additional check is more - * expensive, isn't required by standards, and shouldn't be - * necessary if the group used has a small cofactor. In - * particular, it is useless for the NIST groups which all - * have a cofactor of 1. + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * \param rs_ctx The restart context (NULL disables restart). * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ); /** - * \brief Check that an mbedtls_mpi is a valid private key for this curve + * \brief This function checks that a point is a valid public key + * on this curve. * - * \param grp Group used - * \param d Integer to check + * It only checks that the point is non-zero, has + * valid coordinates and lies on the curve. It does not verify + * that it is indeed a multiple of \p G. This additional + * check is computationally more expensive, is not required + * by standards, and should not be necessary if the group + * used has a small cofactor. In particular, it is useless for + * the NIST groups which all have a cofactor of 1. * - * \return 0 if point is a valid private key, - * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure, to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. + * \param grp The ECP group the point should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to check. This must be initialized. + * + * \return \c 0 if the point is a valid public key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not + * a valid public key for the given curve. + * \return Another negative error code on other kinds of failure. */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ); /** - * \brief Generate a keypair with configurable base point + * \brief This function checks that an \p mbedtls_mpi is a + * valid private key for this curve. * - * \param grp ECP group - * \param G Chosen base point - * \param d Destination MPI (secret part) - * \param Q Destination point (public part) - * \param f_rng RNG function - * \param p_rng RNG parameter + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \param grp The ECP group the private key should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The integer to check. This must be initialized. * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. + * \return \c 0 if the point is a valid private key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid + * private key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ); + +/** + * \brief This function generates a private key. + * + * \param grp The ECP group to generate a private key for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates a keypair with a configurable base + * point. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param G The base point to use. This must be initialized + * and belong to \p grp. It replaces the default base + * point \c grp->G used by mbedtls_ecp_gen_keypair(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. */ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** - * \brief Generate a keypair + * \brief This function generates an ECP keypair. * - * \param grp ECP group - * \param d Destination MPI (secret part) - * \param Q Destination point (public part) - * \param f_rng RNG function - * \param p_rng RNG parameter + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. */ -int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, + mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** - * \brief Generate a keypair + * \brief This function generates an ECP key. * - * \param grp_id ECP group identifier - * \param key Destination keypair - * \param f_rng RNG function - * \param p_rng RNG parameter + * \param grp_id The ECP group identifier. + * \param key The destination key. This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. */ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); /** - * \brief Check a public-private key pair + * \brief This function checks that the keypair objects + * \p pub and \p prv have the same group and the + * same public point, and that the private key in + * \p prv is consistent with the public key. * - * \param pub Keypair structure holding a public key - * \param prv Keypair structure holding a private (plus public) key + * \param pub The keypair structure holding the public key. This + * must be initialized. If it contains a private key, that + * part is ignored. + * \param prv The keypair structure holding the full keypair. + * This must be initialized. * - * \return 0 if successful (keys are valid and match), or - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or - * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code. + * \return \c 0 on success, meaning that the keys are valid and match. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. */ -int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, + const mbedtls_ecp_keypair *prv ); #if defined(MBEDTLS_SELF_TEST) + /** - * \brief Checkup routine + * \brief The ECP checkup routine. * - * \return 0 if successful, or 1 if a test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_ecp_self_test( int verbose ); -#endif + +#endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } diff --git a/Externals/mbedtls/include/mbedtls/ecp_internal.h b/Externals/mbedtls/include/mbedtls/ecp_internal.h new file mode 100644 index 0000000000..7625ed48e1 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/ecp_internal.h @@ -0,0 +1,299 @@ +/** + * \file ecp_internal.h + * + * \brief Function declarations for alternative implementation of elliptic curve + * point arithmetic. + */ +/* + * Copyright (C) 2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +/* + * References: + * + * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. + * + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + * + * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. + * + * + * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic + * Curve Cryptography. + * + * [6] Digital Signature Standard (DSS), FIPS 186-4. + * + * + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * Security (TLS), RFC 4492. + * + * + * [8] + * + * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. + * Springer Science & Business Media, 1 Aug 2000 + */ + +#ifndef MBEDTLS_ECP_INTERNAL_H +#define MBEDTLS_ECP_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); + +#if defined(ECP_SHORTWEIERSTRASS) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Special cases: (1) P or Q is zero, (2) R is zero, + * (3) P == Q. + * None of these cases can happen as intermediate step in + * ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base + * point, the factor being less than its order, so none of + * them is zero; + * - Q is an odd multiple of the base point, P an even + * multiple, due to the choice of precomputed points in the + * modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as + * meaning 1. + * + * Cost in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ); +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ); +#endif + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) +int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); +#endif + +/** + * \brief Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * + * \param grp pointer to the group representing the curve + * + * \param P the point on the curve to be randomised given with + * projective coordinates. This is an input/output parameter. + * + * \param f_rng a function pointer to the random number generator + * + * \param p_rng a pointer to the random number generator state + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) +int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +/** + * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. + * + * \param grp pointer to the group representing the curve + * + * \param P pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) +int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P ); +#endif + +#endif /* ECP_MONTGOMERY */ + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#endif /* ecp_internal.h */ + diff --git a/Externals/mbedtls/include/mbedtls/entropy.h b/Externals/mbedtls/include/mbedtls/entropy.h index 747aca4dfa..ca06dc3c58 100644 --- a/Externals/mbedtls/include/mbedtls/entropy.h +++ b/Externals/mbedtls/include/mbedtls/entropy.h @@ -2,7 +2,8 @@ * \file entropy.h * * \brief Entropy accumulator implementation - * + */ +/* * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -106,7 +107,7 @@ typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, s /** * \brief Entropy source state */ -typedef struct +typedef struct mbedtls_entropy_source_state { mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ void * p_source; /**< The callback data pointer */ @@ -119,8 +120,9 @@ mbedtls_entropy_source_state; /** * \brief Entropy context structure */ -typedef struct +typedef struct mbedtls_entropy_context { + int accumulator_started; #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_context accumulator; #else @@ -164,7 +166,7 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); * \param threshold Minimum required from source before entropy is released * ( with mbedtls_entropy_func() ) (in bytes) * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or - * MBEDTSL_ENTROPY_SOURCE_WEAK. + * MBEDTLS_ENTROPY_SOURCE_WEAK. * At least one strong source needs to be added. * Weaker sources (such as the cycle counter) can be used as * a complement. diff --git a/Externals/mbedtls/include/mbedtls/entropy_poll.h b/Externals/mbedtls/include/mbedtls/entropy_poll.h index 81258d5f39..94dd657eb9 100644 --- a/Externals/mbedtls/include/mbedtls/entropy_poll.h +++ b/Externals/mbedtls/include/mbedtls/entropy_poll.h @@ -2,7 +2,8 @@ * \file entropy_poll.h * * \brief Platform-specific and custom entropy polling functions - * + */ +/* * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * diff --git a/Externals/mbedtls/include/mbedtls/error.h b/Externals/mbedtls/include/mbedtls/error.h index 5e549f6b6a..bee0fe485a 100644 --- a/Externals/mbedtls/include/mbedtls/error.h +++ b/Externals/mbedtls/include/mbedtls/error.h @@ -2,8 +2,9 @@ * \file error.h * * \brief Error to string translation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -23,6 +24,12 @@ #ifndef MBEDTLS_ERROR_H #define MBEDTLS_ERROR_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include /** @@ -49,38 +56,53 @@ * * Module Nr Codes assigned * MPI 7 0x0002-0x0010 - * GCM 2 0x0012-0x0014 - * BLOWFISH 2 0x0016-0x0018 + * GCM 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 * THREADING 3 0x001A-0x001E - * AES 2 0x0020-0x0022 - * CAMELLIA 2 0x0024-0x0026 - * XTEA 1 0x0028-0x0028 + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 * BASE64 2 0x002A-0x002C * OID 1 0x002E-0x002E 0x000B-0x000B * PADLOCK 1 0x0030-0x0030 - * DES 1 0x0032-0x0032 + * DES 2 0x0032-0x0032 0x0033-0x0033 * CTR_DBRG 4 0x0034-0x003A * ENTROPY 3 0x003C-0x0040 0x003D-0x003F - * NET 11 0x0042-0x0052 0x0043-0x0045 + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A * PBKDF2 1 0x007C-0x007C - * HMAC_DRBG 4 0x0003-0x0009 - * CCM 2 0x000D-0x000F + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 0x0073-0x0073 + * SHA256 1 0x0037-0x0037 0x0074-0x0074 + * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 + * PLATFORM 1 0x0070-0x0072 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors * PEM 1 9 * PKCS#12 1 4 (Started from top) - * X509 2 19 + * X509 2 20 * PKCS5 2 4 (Started from top) - * DHM 3 9 - * PK 3 14 (Started from top) - * RSA 4 9 - * ECP 4 8 (Started from top) - * MD 5 4 - * CIPHER 6 6 - * SSL 6 17 (Started from top) - * SSL 7 31 + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 10 (Started from top) + * MD 5 5 + * HKDF 5 1 (Started from top) + * CIPHER 6 8 + * SSL 6 23 (Started from top) + * SSL 7 32 * * Module dependent error code (5 bits 0x.00.-0x.F8.) */ diff --git a/Externals/mbedtls/include/mbedtls/gcm.h b/Externals/mbedtls/include/mbedtls/gcm.h index 1b77aaedd4..fd130abd7c 100644 --- a/Externals/mbedtls/include/mbedtls/gcm.h +++ b/Externals/mbedtls/include/mbedtls/gcm.h @@ -1,9 +1,18 @@ /** * \file gcm.h * - * \brief Galois/Counter mode for 128-bit block ciphers + * \brief This file contains GCM definitions and functions. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,11 +27,18 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_GCM_H #define MBEDTLS_GCM_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "cipher.h" #include @@ -31,46 +47,69 @@ #define MBEDTLS_GCM_DECRYPT 0 #define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ + #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_GCM_ALT) + /** - * \brief GCM context structure + * \brief The GCM context structure. */ -typedef struct { - mbedtls_cipher_context_t cipher_ctx;/*!< cipher context used */ - uint64_t HL[16]; /*!< Precalculated HTable */ - uint64_t HH[16]; /*!< Precalculated HTable */ - uint64_t len; /*!< Total data length */ - uint64_t add_len; /*!< Total add length */ - unsigned char base_ectr[16];/*!< First ECTR for tag */ - unsigned char y[16]; /*!< Y working value */ - unsigned char buf[16]; /*!< buf working value */ - int mode; /*!< Encrypt or Decrypt */ +typedef struct mbedtls_gcm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint64_t len; /*!< The total length of the encrypted data. */ + uint64_t add_len; /*!< The total length of the additional data. */ + unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ + unsigned char y[16]; /*!< The Y working value. */ + unsigned char buf[16]; /*!< The buf working value. */ + int mode; /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ } mbedtls_gcm_context; +#else /* !MBEDTLS_GCM_ALT */ +#include "gcm_alt.h" +#endif /* !MBEDTLS_GCM_ALT */ + /** - * \brief Initialize GCM context (just makes references valid) - * Makes the context ready for mbedtls_gcm_setkey() or - * mbedtls_gcm_free(). + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). * - * \param ctx GCM context to initialize + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. This must not be \c NULL. */ void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); /** - * \brief GCM initialization (encryption) + * \brief This function associates a GCM context with a + * cipher algorithm and a key. * - * \param ctx GCM context to be initialized - * \param cipher cipher to use (a 128-bit block cipher) - * \param key encryption key - * \param keybits must be 128, 192 or 256 + * \param ctx The GCM context. This must be initialized. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must be a readable buffer of at + * least \p keybits bits. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
* - * \return 0 if successful, or a cipher specific error code + * \return \c 0 on success. + * \return A cipher-specific error code on failure. */ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, mbedtls_cipher_id_t cipher, @@ -78,26 +117,55 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, unsigned int keybits ); /** - * \brief GCM buffer encryption/decryption using a block cipher + * \brief This function performs GCM encryption or decryption of a buffer. * - * \note On encryption, the output buffer can be the same as the input buffer. - * On decryption, the output buffer cannot be the same as input buffer. - * If buffers overlap, the output buffer must trail at least 8 bytes - * behind the input buffer. + * \note For encryption, the output buffer can be the same as the + * input buffer. For decryption, the output buffer cannot be + * the same as input buffer. If the buffers overlap, the output + * buffer must trail at least 8 Bytes behind the input buffer. * - * \param ctx GCM context - * \param mode MBEDTLS_GCM_ENCRYPT or MBEDTLS_GCM_DECRYPT - * \param length length of the input data - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data - * \param add_len length of additional data - * \param input buffer holding the input data - * \param output buffer for holding the output data - * \param tag_len length of the tag to generate - * \param tag buffer for holding the tag + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. * - * \return 0 if successful + * \param ctx The GCM context to use for encryption or decryption. This + * must be initialized. + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is greater + * than zero, this must be a writable buffer of at least that + * size in Bytes. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the encryption + * or decryption failed. */ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, int mode, @@ -112,25 +180,37 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, unsigned char *tag ); /** - * \brief GCM buffer authenticated decryption using a block cipher + * \brief This function performs a GCM authenticated decryption of a + * buffer. * - * \note On decryption, the output buffer cannot be the same as input buffer. - * If buffers overlap, the output buffer must trail at least 8 bytes - * behind the input buffer. + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. * - * \param ctx GCM context - * \param length length of the input data - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data - * \param add_len length of additional data - * \param tag buffer holding the tag - * \param tag_len length of the tag - * \param input buffer holding the input data - * \param output buffer for holding the output data + * \param ctx The GCM context. This must be initialized. + * \param length The length of the ciphertext to decrypt, which is also + * the length of the decrypted plaintext. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag to verify. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size. + * \param output The buffer for holding the decrypted plaintext. If \p length + * is greater than zero, this must be a writable buffer of at + * least that size. * - * \return 0 if successful and authenticated, - * MBEDTLS_ERR_GCM_AUTH_FAILED if tag does not match + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the decryption + * failed. */ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, size_t length, @@ -144,16 +224,21 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, unsigned char *output ); /** - * \brief Generic GCM stream start function + * \brief This function starts a GCM encryption or decryption + * operation. * - * \param ctx GCM context - * \param mode MBEDTLS_GCM_ENCRYPT or MBEDTLS_GCM_DECRYPT - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data (or NULL if length is 0) - * \param add_len length of additional data + * \param ctx The GCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data, or \c NULL + * if \p add_len is \c 0. + * \param add_len The length of the additional data. If \c 0, + * \p add may be \c NULL. * - * \return 0 if successful + * \return \c 0 on success. */ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, int mode, @@ -163,21 +248,29 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, size_t add_len ); /** - * \brief Generic GCM update function. Encrypts/decrypts using the - * given GCM context. Expects input to be a multiple of 16 - * bytes! Only the last call before mbedtls_gcm_finish() can be less - * than 16 bytes! + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. * - * \note On decryption, the output buffer cannot be the same as input buffer. - * If buffers overlap, the output buffer must trail at least 8 bytes - * behind the input buffer. + * ` The function expects input to be a multiple of 16 + * Bytes. Only the last call before calling + * mbedtls_gcm_finish() can be less than 16 Bytes. * - * \param ctx GCM context - * \param length length of the input data - * \param input buffer holding the input data - * \param output buffer for holding the output data + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. * - * \return 0 if successful or MBEDTLS_ERR_GCM_BAD_INPUT + * \param ctx The GCM context. This must be initialized. + * \param length The length of the input data. This must be a multiple of + * 16 except in the last call before mbedtls_gcm_finish(). + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is + * greater than zero, this must be a writable buffer of at + * least that size in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. */ int mbedtls_gcm_update( mbedtls_gcm_context *ctx, size_t length, @@ -185,36 +278,49 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx, unsigned char *output ); /** - * \brief Generic GCM finalisation function. Wraps up the GCM stream - * and generates the tag. The tag can have a maximum length of - * 16 bytes. + * \brief This function finishes the GCM operation and generates + * the authentication tag. * - * \param ctx GCM context - * \param tag buffer for holding the tag - * \param tag_len length of the tag to generate (must be at least 4) + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. * - * \return 0 if successful or MBEDTLS_ERR_GCM_BAD_INPUT + * \param ctx The GCM context. This must be initialized. + * \param tag The buffer for holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to generate. This must be at least + * four. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. */ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, unsigned char *tag, size_t tag_len ); /** - * \brief Free a GCM context and underlying cipher sub-context + * \brief This function clears a GCM context and the underlying + * cipher sub-context. * - * \param ctx GCM context to free + * \param ctx The GCM context to clear. If this is \c NULL, the call has + * no effect. Otherwise, this must be initialized. */ void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); +#if defined(MBEDTLS_SELF_TEST) + /** - * \brief Checkup routine + * \brief The GCM checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_gcm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif + #endif /* gcm.h */ diff --git a/Externals/mbedtls/include/mbedtls/havege.h b/Externals/mbedtls/include/mbedtls/havege.h index dac5d31138..4c1c86087a 100644 --- a/Externals/mbedtls/include/mbedtls/havege.h +++ b/Externals/mbedtls/include/mbedtls/havege.h @@ -2,7 +2,8 @@ * \file havege.h * * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_HAVEGE_H #define MBEDTLS_HAVEGE_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include #define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 @@ -34,7 +41,7 @@ extern "C" { /** * \brief HAVEGE state structure */ -typedef struct +typedef struct mbedtls_havege_state { int PT1, PT2, offset[2]; int pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; diff --git a/Externals/mbedtls/include/mbedtls/hkdf.h b/Externals/mbedtls/include/mbedtls/hkdf.h new file mode 100644 index 0000000000..40ee64eb03 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/hkdf.h @@ -0,0 +1,141 @@ +/** + * \file hkdf.h + * + * \brief This file contains the HKDF interface. + * + * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is + * specified by RFC 5869. + */ +/* + * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ +#ifndef MBEDTLS_HKDF_H +#define MBEDTLS_HKDF_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +/** + * \name HKDF Error codes + * \{ + */ +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function + * (HKDF). + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros of + * md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +/** + * \brief Take the input keying material \p ikm and extract from it a + * fixed-length pseudorandom key \p prk. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the + * hash function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros + * of md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param[out] prk A pseudorandom key of at least md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +/** + * \brief Expand the supplied \p prk into several additional pseudorandom + * keys, which is the output of the HKDF. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is + * usually the output from the HKDF extract step. + * \param prk_len The length in bytes of \p prk. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* hkdf.h */ diff --git a/Externals/mbedtls/include/mbedtls/hmac_drbg.h b/Externals/mbedtls/include/mbedtls/hmac_drbg.h index e010558028..7eae32bbd6 100644 --- a/Externals/mbedtls/include/mbedtls/hmac_drbg.h +++ b/Externals/mbedtls/include/mbedtls/hmac_drbg.h @@ -2,7 +2,8 @@ * \file hmac_drbg.h * * \brief HMAC_DRBG (NIST SP 800-90A) - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,10 +24,16 @@ #ifndef MBEDTLS_HMAC_DRBG_H #define MBEDTLS_HMAC_DRBG_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "md.h" #if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" +#include "threading.h" #endif /* @@ -73,7 +80,7 @@ extern "C" { /** * HMAC_DRBG context. */ -typedef struct +typedef struct mbedtls_hmac_drbg_context { /* Working state: the key K is not stored explicitely, * but is implied by the HMAC context */ @@ -194,10 +201,13 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, * \param additional Additional data to update state with, or NULL * \param add_len Length of additional data, or 0 * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + * * \note Additional data is optional, pass NULL and 0 as second * third argument if no additional data is being used. */ -void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len ); /** @@ -256,6 +266,31 @@ int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len */ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief HMAC_DRBG update state + * + * \deprecated Superseded by mbedtls_hmac_drbg_update_ret() + * in 2.16.0. + * + * \param ctx HMAC_DRBG context + * \param additional Additional data to update state with, or NULL + * \param add_len Length of additional data, or 0 + * + * \note Additional data is optional, pass NULL and 0 as second + * third argument if no additional data is being used. + */ +MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( + mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + #if defined(MBEDTLS_FS_IO) /** * \brief Write a seed file diff --git a/Externals/mbedtls/include/mbedtls/md.h b/Externals/mbedtls/include/mbedtls/md.h index 9b996a951b..8bcf766a6c 100644 --- a/Externals/mbedtls/include/mbedtls/md.h +++ b/Externals/mbedtls/include/mbedtls/md.h @@ -1,11 +1,12 @@ -/** + /** * \file md.h * - * \brief Generic message digest wrapper + * \brief This file contains the generic message-digest wrapper. * * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -20,33 +21,51 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ + #ifndef MBEDTLS_MD_H #define MBEDTLS_MD_H #include +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ #define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ #define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ +/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ + #ifdef __cplusplus extern "C" { #endif +/** + * \brief Supported message digests. + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ typedef enum { - MBEDTLS_MD_NONE=0, - MBEDTLS_MD_MD2, - MBEDTLS_MD_MD4, - MBEDTLS_MD_MD5, - MBEDTLS_MD_SHA1, - MBEDTLS_MD_SHA224, - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA384, - MBEDTLS_MD_SHA512, - MBEDTLS_MD_RIPEMD160, + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD2, /**< The MD2 message digest. */ + MBEDTLS_MD_MD4, /**< The MD4 message digest. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ } mbedtls_md_type_t; #if defined(MBEDTLS_SHA512_C) @@ -56,65 +75,80 @@ typedef enum { #endif /** - * Opaque struct defined in md_internal.h + * Opaque struct defined in md_internal.h. */ typedef struct mbedtls_md_info_t mbedtls_md_info_t; /** - * Generic message digest context. + * The generic message-digest context. */ -typedef struct { - /** Information about the associated message digest */ +typedef struct mbedtls_md_context_t +{ + /** Information about the associated message digest. */ const mbedtls_md_info_t *md_info; - /** Digest-specific context */ + /** The digest-specific context. */ void *md_ctx; - /** HMAC part of the context */ + /** The HMAC part of the context. */ void *hmac_ctx; } mbedtls_md_context_t; /** - * \brief Returns the list of digests supported by the generic digest module. + * \brief This function returns the list of digests supported by the + * generic digest module. * - * \return a statically allocated array of digests, the last entry - * is 0. + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. */ const int *mbedtls_md_list( void ); /** - * \brief Returns the message digest information associated with the - * given digest name. + * \brief This function returns the message-digest information + * associated with the given digest name. * - * \param md_name Name of the digest to search for. + * \param md_name The name of the digest to search for. * - * \return The message digest information associated with md_name or - * NULL if not found. + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); /** - * \brief Returns the message digest information associated with the - * given digest type. + * \brief This function returns the message-digest information + * associated with the given digest type. * - * \param md_type type of digest to search for. + * \param md_type The type of digest to search for. * - * \return The message digest information associated with md_type or - * NULL if not found. + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); /** - * \brief Initialize a md_context (as NONE) - * This should always be called first. - * Prepares the context for mbedtls_md_setup() or mbedtls_md_free(). + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. */ void mbedtls_md_init( mbedtls_md_context_t *ctx ); /** - * \brief Free and clear the internal structures of ctx. - * Can be called at any time after mbedtls_md_init(). - * Mandatory once mbedtls_md_setup() has been called. + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). */ void mbedtls_md_free( mbedtls_md_context_t *ctx ); @@ -125,220 +159,300 @@ void mbedtls_md_free( mbedtls_md_context_t *ctx ); #define MBEDTLS_DEPRECATED #endif /** - * \brief Select MD to use and allocate internal structures. - * Should be called after mbedtls_md_init() or mbedtls_md_free(). + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or mbedtls_md_free(). * Makes it necessary to call mbedtls_md_free() later. * * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 * - * \param ctx Context to set up. - * \param md_info Message digest to use. + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. * - * \returns \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, - * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; #undef MBEDTLS_DEPRECATED #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** - * \brief Select MD to use and allocate internal structures. - * Should be called after mbedtls_md_init() or mbedtls_md_free(). - * Makes it necessary to call mbedtls_md_free() later. + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. * - * \param ctx Context to set up. - * \param md_info Message digest to use. - * \param hmac 0 to save some memory if HMAC will not be used, - * non-zero is HMAC is going to be used with this context. + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. * - * \returns \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, - * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); /** - * \brief Clone the state of an MD context + * \brief This function clones the state of an message-digest + * context. * - * \note The two contexts must have been setup to the same type - * (cloning from SHA-256 to SHA-512 make no sense). + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. * - * \warning Only clones the MD state, not the HMAC state! (for now) + * \note The two contexts must have the same type, + * for example, both are SHA-256. * - * \param dst The destination context - * \param src The context to be cloned + * \warning This function clones the message-digest state, not the + * HMAC state. * - * \return \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. */ int mbedtls_md_clone( mbedtls_md_context_t *dst, const mbedtls_md_context_t *src ); /** - * \brief Returns the size of the message digest output. + * \brief This function extracts the message-digest size from the + * message-digest information structure. * - * \param md_info message digest info + * \param md_info The information structure of the message-digest algorithm + * to use. * - * \return size of the message digest output in bytes. + * \return The size of the message-digest output in Bytes. */ unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); /** - * \brief Returns the type of the message digest output. + * \brief This function extracts the message-digest type from the + * message-digest information structure. * - * \param md_info message digest info + * \param md_info The information structure of the message-digest algorithm + * to use. * - * \return type of the message digest output. + * \return The type of the message digest. */ mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); /** - * \brief Returns the name of the message digest output. + * \brief This function extracts the message-digest name from the + * message-digest information structure. * - * \param md_info message digest info + * \param md_info The information structure of the message-digest algorithm + * to use. * - * \return name of the message digest output. + * \return The name of the message digest. */ const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); /** - * \brief Prepare the context to digest a new message. - * Generally called after mbedtls_md_setup() or mbedtls_md_finish(). - * Followed by mbedtls_md_update(). + * \brief This function starts a message-digest computation. * - * \param ctx generic message digest context. + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The generic message-digest context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_starts( mbedtls_md_context_t *ctx ); /** - * \brief Generic message digest process buffer - * Called between mbedtls_md_starts() and mbedtls_md_finish(). - * May be called repeatedly. + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. * - * \param ctx Generic message digest context - * \param input buffer holding the datal - * \param ilen length of the input data + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); /** - * \brief Generic message digest final digest - * Called after mbedtls_md_update(). - * Usually followed by mbedtls_md_free() or mbedtls_md_starts(). + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. * - * \param ctx Generic message digest context - * \param output Generic message digest checksum result + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); /** - * \brief Output = message_digest( input buffer ) + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. * - * \param md_info message digest info - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic message digest checksum result + * The result is calculated as + * Output = message_digest(input buffer). * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output ); #if defined(MBEDTLS_FS_IO) /** - * \brief Output = message_digest( file contents ) + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. * - * \param md_info message digest info - * \param path input file name - * \param output generic message digest checksum result + * The result is calculated as + * Output = message_digest(file contents). * - * \return 0 if successful, - * MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, - * MBEDTLS_ERR_MD_BAD_INPUT_DATA if md_info was NULL. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. */ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ); #endif /* MBEDTLS_FS_IO */ /** - * \brief Set HMAC key and prepare to authenticate a new message. - * Usually called after mbedtls_md_setup() or mbedtls_md_hmac_finish(). + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. * - * \param ctx HMAC context - * \param key HMAC secret key - * \param keylen length of the HMAC key in bytes + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ); /** - * \brief Generic HMAC process buffer. - * Called between mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() - * and mbedtls_md_hmac_finish(). - * May be called repeatedly. + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); /** - * \brief Output HMAC. - * Called after mbedtls_md_hmac_update(). - * Usually followed by mbedtls_md_hmac_reset(), - * mbedtls_md_hmac_starts(), or mbedtls_md_free(). + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. * - * \param ctx HMAC context - * \param output Generic HMAC checksum result + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); /** - * \brief Prepare to authenticate a new message with the same key. - * Called after mbedtls_md_hmac_finish() and before - * mbedtls_md_hmac_update(). + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. * - * \param ctx HMAC context to be reset + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); /** - * \brief Output = Generic_HMAC( hmac key, input buffer ) + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. * - * \param md_info message digest info - * \param key HMAC secret key - * \param keylen length of the HMAC key in bytes - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic HMAC-result + * The function allocates the context, performs the + * calculation, and frees the context. * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. */ int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, diff --git a/Externals/mbedtls/include/mbedtls/md2.h b/Externals/mbedtls/include/mbedtls/md2.h index 0f93fbf427..fe97cf08d4 100644 --- a/Externals/mbedtls/include/mbedtls/md2.h +++ b/Externals/mbedtls/include/mbedtls/md2.h @@ -3,6 +3,11 @@ * * \brief MD2 message digest algorithm (hash function) * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -19,6 +24,7 @@ * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) + * */ #ifndef MBEDTLS_MD2_H #define MBEDTLS_MD2_H @@ -31,18 +37,26 @@ #include -#if !defined(MBEDTLS_MD2_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + /** * \brief MD2 context structure + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -typedef struct +typedef struct mbedtls_md2_context { unsigned char cksum[16]; /*!< checksum of the data block */ unsigned char state[48]; /*!< intermediate digest state */ @@ -51,10 +65,19 @@ typedef struct } mbedtls_md2_context; +#else /* MBEDTLS_MD2_ALT */ +#include "md2_alt.h" +#endif /* MBEDTLS_MD2_ALT */ + /** * \brief Initialize MD2 context * * \param ctx MD2 context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md2_init( mbedtls_md2_context *ctx ); @@ -62,6 +85,11 @@ void mbedtls_md2_init( mbedtls_md2_context *ctx ); * \brief Clear MD2 context * * \param ctx MD2 context to be cleared + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md2_free( mbedtls_md2_context *ctx ); @@ -70,6 +98,11 @@ void mbedtls_md2_free( mbedtls_md2_context *ctx ); * * \param dst The destination context * \param src The context to be cloned + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md2_clone( mbedtls_md2_context *dst, const mbedtls_md2_context *src ); @@ -78,56 +111,193 @@ void mbedtls_md2_clone( mbedtls_md2_context *dst, * \brief MD2 context setup * * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md2_starts( mbedtls_md2_context *ctx ); +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ); /** * \brief MD2 process buffer * * \param ctx MD2 context - * \param input buffer holding the data + * \param input buffer holding the data * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ); +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); /** * \brief MD2 final digest * * \param ctx MD2 context * \param output MD2 checksum result + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ); +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ); -#ifdef __cplusplus -} +/** + * \brief MD2 process data block (internal use only) + * + * \param ctx MD2 context + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED #endif +/** + * \brief MD2 context setup + * + * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx ); -#else /* MBEDTLS_MD2_ALT */ -#include "md2_alt.h" -#endif /* MBEDTLS_MD2_ALT */ +/** + * \brief MD2 process buffer + * + * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); -#ifdef __cplusplus -extern "C" { -#endif +/** + * \brief MD2 final digest + * + * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 + * + * \param ctx MD2 context + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Output = MD2( input buffer ) * - * \param input buffer holding the data + * \param input buffer holding the data * \param ilen length of the input data * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ); +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD2( input buffer ) + * + * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ int mbedtls_md2_self_test( int verbose ); -/* Internal use */ -void mbedtls_md2_process( mbedtls_md2_context *ctx ); +#endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } diff --git a/Externals/mbedtls/include/mbedtls/md4.h b/Externals/mbedtls/include/mbedtls/md4.h index 45214d41d9..ce703c0ba4 100644 --- a/Externals/mbedtls/include/mbedtls/md4.h +++ b/Externals/mbedtls/include/mbedtls/md4.h @@ -3,6 +3,11 @@ * * \brief MD4 message digest algorithm (hash function) * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -19,6 +24,7 @@ * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) + * */ #ifndef MBEDTLS_MD4_H #define MBEDTLS_MD4_H @@ -32,18 +38,26 @@ #include #include -#if !defined(MBEDTLS_MD4_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + /** * \brief MD4 context structure + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -typedef struct +typedef struct mbedtls_md4_context { uint32_t total[2]; /*!< number of bytes processed */ uint32_t state[4]; /*!< intermediate digest state */ @@ -51,10 +65,19 @@ typedef struct } mbedtls_md4_context; +#else /* MBEDTLS_MD4_ALT */ +#include "md4_alt.h" +#endif /* MBEDTLS_MD4_ALT */ + /** * \brief Initialize MD4 context * * \param ctx MD4 context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md4_init( mbedtls_md4_context *ctx ); @@ -62,6 +85,11 @@ void mbedtls_md4_init( mbedtls_md4_context *ctx ); * \brief Clear MD4 context * * \param ctx MD4 context to be cleared + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md4_free( mbedtls_md4_context *ctx ); @@ -70,6 +98,11 @@ void mbedtls_md4_free( mbedtls_md4_context *ctx ); * * \param dst The destination context * \param src The context to be cloned + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md4_clone( mbedtls_md4_context *dst, const mbedtls_md4_context *src ); @@ -78,56 +111,198 @@ void mbedtls_md4_clone( mbedtls_md4_context *dst, * \brief MD4 context setup * * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. */ -void mbedtls_md4_starts( mbedtls_md4_context *ctx ); +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ); /** * \brief MD4 process buffer * * \param ctx MD4 context - * \param input buffer holding the data + * \param input buffer holding the data * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ); +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); /** * \brief MD4 final digest * * \param ctx MD4 context * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ); +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ); -#ifdef __cplusplus -} +/** + * \brief MD4 process data block (internal use only) + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED #endif +/** + * \brief MD4 context setup + * + * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx ); -#else /* MBEDTLS_MD4_ALT */ -#include "md4_alt.h" -#endif /* MBEDTLS_MD4_ALT */ +/** + * \brief MD4 process buffer + * + * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); -#ifdef __cplusplus -extern "C" { -#endif +/** + * \brief MD4 final digest + * + * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Output = MD4( input buffer ) * - * \param input buffer holding the data + * \param input buffer holding the data * \param ilen length of the input data * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ); +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD4( input buffer ) + * + * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ int mbedtls_md4_self_test( int verbose ); -/* Internal use */ -void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ); +#endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } diff --git a/Externals/mbedtls/include/mbedtls/md5.h b/Externals/mbedtls/include/mbedtls/md5.h index 5a64061aa0..6eed6cc864 100644 --- a/Externals/mbedtls/include/mbedtls/md5.h +++ b/Externals/mbedtls/include/mbedtls/md5.h @@ -3,6 +3,11 @@ * * \brief MD5 message digest algorithm (hash function) * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -32,18 +37,26 @@ #include #include -#if !defined(MBEDTLS_MD5_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + /** * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -typedef struct +typedef struct mbedtls_md5_context { uint32_t total[2]; /*!< number of bytes processed */ uint32_t state[4]; /*!< intermediate digest state */ @@ -51,10 +64,19 @@ typedef struct } mbedtls_md5_context; +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + /** * \brief Initialize MD5 context * * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md5_init( mbedtls_md5_context *ctx ); @@ -62,6 +84,11 @@ void mbedtls_md5_init( mbedtls_md5_context *ctx ); * \brief Clear MD5 context * * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md5_free( mbedtls_md5_context *ctx ); @@ -70,6 +97,11 @@ void mbedtls_md5_free( mbedtls_md5_context *ctx ); * * \param dst The destination context * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ void mbedtls_md5_clone( mbedtls_md5_context *dst, const mbedtls_md5_context *src ); @@ -78,57 +110,200 @@ void mbedtls_md5_clone( mbedtls_md5_context *dst, * \brief MD5 context setup * * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md5_starts( mbedtls_md5_context *ctx ); +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); /** * \brief MD5 process buffer * * \param ctx MD5 context - * \param input buffer holding the data + * \param input buffer holding the data * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ); +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); /** * \brief MD5 final digest * * \param ctx MD5 context * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ); +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); -/* Internal use */ -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ); +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); -#ifdef __cplusplus -} +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED #endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); -#else /* MBEDTLS_MD5_ALT */ -#include "md5_alt.h" -#endif /* MBEDTLS_MD5_ALT */ +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); -#ifdef __cplusplus -extern "C" { -#endif +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Output = MD5( input buffer ) * - * \param input buffer holding the data + * \param input buffer holding the data * \param ilen length of the input data * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ int mbedtls_md5_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/md_internal.h b/Externals/mbedtls/include/mbedtls/md_internal.h index e2441bbc49..04de482918 100644 --- a/Externals/mbedtls/include/mbedtls/md_internal.h +++ b/Externals/mbedtls/include/mbedtls/md_internal.h @@ -6,7 +6,8 @@ * \warning This in an internal header. Do not include directly. * * \author Adriaan de Jong - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -58,17 +59,17 @@ struct mbedtls_md_info_t int block_size; /** Digest initialisation function */ - void (*starts_func)( void *ctx ); + int (*starts_func)( void *ctx ); /** Digest update function */ - void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + int (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); /** Digest finalisation function */ - void (*finish_func)( void *ctx, unsigned char *output ); + int (*finish_func)( void *ctx, unsigned char *output ); /** Generic digest function */ - void (*digest_func)( const unsigned char *input, size_t ilen, - unsigned char *output ); + int (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); /** Allocate a new context */ void * (*ctx_alloc_func)( void ); @@ -80,7 +81,7 @@ struct mbedtls_md_info_t void (*clone_func)( void *dst, const void *src ); /** Internal use only */ - void (*process_func)( void *ctx, const unsigned char *input ); + int (*process_func)( void *ctx, const unsigned char *input ); }; #if defined(MBEDTLS_MD2_C) diff --git a/Externals/mbedtls/include/mbedtls/memory_buffer_alloc.h b/Externals/mbedtls/include/mbedtls/memory_buffer_alloc.h index d5df316fdd..705f9a6369 100644 --- a/Externals/mbedtls/include/mbedtls/memory_buffer_alloc.h +++ b/Externals/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -2,7 +2,8 @@ * \file memory_buffer_alloc.h * * \brief Buffer-based memory allocator - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * diff --git a/Externals/mbedtls/include/mbedtls/net.h b/Externals/mbedtls/include/mbedtls/net.h index 774559b3cf..8cead58e5d 100644 --- a/Externals/mbedtls/include/mbedtls/net.h +++ b/Externals/mbedtls/include/mbedtls/net.h @@ -1,8 +1,11 @@ /** * \file net.h * - * \brief Deprecated header file that includes mbedtls/net_sockets.h + * \brief Deprecated header file that includes net_sockets.h * + * \deprecated Superseded by mbedtls/net_sockets.h + */ +/* * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -19,12 +22,15 @@ * limitations under the License. * * This file is part of mbed TLS (https://tls.mbed.org) - * - * \deprecated Superseded by mbedtls/net_sockets.h */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) -#include "mbedtls/net_sockets.h" +#include "net_sockets.h" #if defined(MBEDTLS_DEPRECATED_WARNING) #warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" #endif /* MBEDTLS_DEPRECATED_WARNING */ diff --git a/Externals/mbedtls/include/mbedtls/net_sockets.h b/Externals/mbedtls/include/mbedtls/net_sockets.h index de335526fe..4c7ef00fe6 100644 --- a/Externals/mbedtls/include/mbedtls/net_sockets.h +++ b/Externals/mbedtls/include/mbedtls/net_sockets.h @@ -1,8 +1,25 @@ /** * \file net_sockets.h * - * \brief Network communication functions + * \brief Network sockets abstraction layer to integrate Mbed TLS into a + * BSD-style sockets API. * + * The network sockets module provides an example integration of the + * Mbed TLS library into a BSD sockets implementation. The module is + * intended to be an example of how Mbed TLS can be integrated into a + * networking stack, as well as to be Mbed TLS's network integration + * for its supported platforms. + * + * The module is intended only to be used with the Mbed TLS library and + * is not intended to be used by third party application software + * directly. + * + * The supported platforms are as follows: + * * Microsoft Windows and Windows CE + * * POSIX/Unix platforms including Linux, OS X + * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -45,12 +62,17 @@ #define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ #define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ #define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ +#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /**< Polling the net context failed. */ +#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 /**< Input invalid. */ #define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ #define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ #define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ +#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */ +#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */ + #ifdef __cplusplus extern "C" { #endif @@ -62,7 +84,7 @@ extern "C" { * (eg two file descriptors for combined IPv4 + IPv6 support, or additional * structures for hand-made UDP demultiplexing). */ -typedef struct +typedef struct mbedtls_net_context { int fd; /**< The underlying file descriptor */ } @@ -117,9 +139,10 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char * * \param bind_ctx Relevant socket * \param client_ctx Will contain the connected client socket - * \param client_ip Will contain the client IP address + * \param client_ip Will contain the client IP address, can be NULL * \param buf_size Size of the client_ip buffer - * \param ip_len Will receive the size of the client IP written + * \param ip_len Will receive the size of the client IP written, + * can be NULL if client_ip is null * * \return 0 if successful, or * MBEDTLS_ERR_NET_ACCEPT_FAILED, or @@ -131,6 +154,29 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, void *client_ip, size_t buf_size, size_t *ip_len ); +/** + * \brief Check and wait for the context to be ready for read/write + * + * \param ctx Socket to check + * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and + * MBEDTLS_NET_POLL_WRITE specifying the events + * to wait for: + * - If MBEDTLS_NET_POLL_READ is set, the function + * will return as soon as the net context is available + * for reading. + * - If MBEDTLS_NET_POLL_WRITE is set, the function + * will return as soon as the net context is available + * for writing. + * \param timeout Maximal amount of time to wait before returning, + * in milliseconds. If \c timeout is zero, the + * function returns immediately. If \c timeout is + * -1u, the function blocks potentially indefinitely. + * + * \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE + * on success or timeout, or a negative return code otherwise. + */ +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ); + /** * \brief Set the socket blocking * diff --git a/Externals/mbedtls/include/mbedtls/nist_kw.h b/Externals/mbedtls/include/mbedtls/nist_kw.h new file mode 100644 index 0000000000..3b67b59cd2 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/nist_kw.h @@ -0,0 +1,184 @@ +/** + * \file nist_kw.h + * + * \brief This file provides an API for key wrapping (KW) and key wrapping with + * padding (KWP) as defined in NIST SP 800-38F. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * + * Key wrapping specifies a deterministic authenticated-encryption mode + * of operation, according to NIST SP 800-38F: Recommendation for + * Block Cipher Modes of Operation: Methods for Key Wrapping. Its + * purpose is to protect cryptographic keys. + * + * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. + * https://tools.ietf.org/html/rfc3394 + * https://tools.ietf.org/html/rfc5649 + * + */ +/* + * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +#ifndef MBEDTLS_NIST_KW_H +#define MBEDTLS_NIST_KW_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_KW_MODE_KW = 0, + MBEDTLS_KW_MODE_KWP = 1 +} mbedtls_nist_kw_mode_t; + +#if !defined(MBEDTLS_NIST_KW_ALT) +// Regular implementation +// + +/** + * \brief The key wrapping context-type definition. The key wrapping context is passed + * to the APIs called. + * + * \note The definition of this type may change in future library versions. + * Don't make any assumptions on this context! + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} mbedtls_nist_kw_context; + +#else /* MBEDTLS_NIST_key wrapping_ALT */ +#include "nist_kw_alt.h" +#endif /* MBEDTLS_NIST_KW_ALT */ + +/** + * \brief This function initializes the specified key wrapping context + * to make references valid and prepare the context + * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). + * + * \param ctx The key wrapping context to initialize. + * + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function initializes the key wrapping context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The key wrapping context. + * \param cipher The 128-bit block cipher to use. Only AES is supported. + * \param key The Key Encryption Key (KEK). + * \param keybits The KEK size in bits. This must be acceptable by the cipher. + * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. + * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers + * which are not supported. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ); + +/** + * \brief This function releases and clears the specified key wrapping context + * and underlying cipher sub-context. + * + * \param ctx The key wrapping context to clear. + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function encrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for encryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
  • + *
  • For KWP mode: any length between 1 and 2^32-1 inclusive.
+ * \param[out] output The buffer holding the output data. + *
  • For KW mode: Must be at least 8 bytes larger than \p in_len.
  • + *
  • For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of + * 8 bytes for KWP (15 bytes at most).
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size ); + +/** + * \brief This function decrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for decryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * The input must be a multiple of semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
  • + *
  • For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
+ * \param[out] output The buffer holding the output data. + * The output buffer's minimal length is 8 bytes shorter than \p in_len. + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, + * depending on how much padding was added to the data. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size); + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The key wrapping checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_nist_kw_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_NIST_KW_H */ diff --git a/Externals/mbedtls/include/mbedtls/oid.h b/Externals/mbedtls/include/mbedtls/oid.h index fcecdafdca..6fbd018aaa 100644 --- a/Externals/mbedtls/include/mbedtls/oid.h +++ b/Externals/mbedtls/include/mbedtls/oid.h @@ -2,7 +2,8 @@ * \file oid.h * * \brief Object Identifier (OID) database - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -96,6 +97,8 @@ /* ISO arc for standard certificate and CRL extensions */ #define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + /** * Private Internet Extensions * { iso(1) identified-organization(3) dod(6) internet(1) @@ -218,21 +221,42 @@ #define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ #define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ #define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + /* * Encryption algorithms */ #define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ #define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ /* * PKCS#5 OIDs */ @@ -379,7 +403,8 @@ extern "C" { /** * \brief Base OID descriptor structure */ -typedef struct { +typedef struct mbedtls_oid_descriptor_t +{ const char *asn1; /*!< OID ASN.1 representation */ size_t asn1_len; /*!< length of asn1 */ const char *name; /*!< official name (e.g. from RFC) */ @@ -513,6 +538,16 @@ int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); #endif /* MBEDTLS_MD_C */ /** diff --git a/Externals/mbedtls/include/mbedtls/padlock.h b/Externals/mbedtls/include/mbedtls/padlock.h index 2045a5ab64..f05b72b077 100644 --- a/Externals/mbedtls/include/mbedtls/padlock.h +++ b/Externals/mbedtls/include/mbedtls/padlock.h @@ -4,6 +4,10 @@ * \brief VIA PadLock ACE for HW encryption/decryption supported by some * processors * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -24,6 +28,12 @@ #ifndef MBEDTLS_PADLOCK_H #define MBEDTLS_PADLOCK_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "aes.h" #define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ @@ -56,7 +66,10 @@ extern "C" { #endif /** - * \brief PadLock detection routine + * \brief Internal PadLock detection routine + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param feature The feature to detect * @@ -65,7 +78,10 @@ extern "C" { int mbedtls_padlock_has_support( int feature ); /** - * \brief PadLock AES-ECB block en(de)cryption + * \brief Internal PadLock AES-ECB block en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT @@ -75,12 +91,15 @@ int mbedtls_padlock_has_support( int feature ); * \return 0 if success, 1 if operation failed */ int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); + int mode, + const unsigned char input[16], + unsigned char output[16] ); /** - * \brief PadLock AES-CBC buffer en(de)cryption + * \brief Internal PadLock AES-CBC buffer en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT @@ -92,11 +111,11 @@ int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, * \return 0 if success, 1 if operation failed */ int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); #ifdef __cplusplus } diff --git a/Externals/mbedtls/include/mbedtls/pem.h b/Externals/mbedtls/include/mbedtls/pem.h index 54dc02d7cd..a29e9ce300 100644 --- a/Externals/mbedtls/include/mbedtls/pem.h +++ b/Externals/mbedtls/include/mbedtls/pem.h @@ -2,7 +2,8 @@ * \file pem.h * * \brief Privacy Enhanced Mail (PEM) decoding - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_PEM_H #define MBEDTLS_PEM_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include /** @@ -50,7 +57,7 @@ extern "C" { /** * \brief PEM context structure */ -typedef struct +typedef struct mbedtls_pem_context { unsigned char *buf; /*!< buffer for decoded data */ size_t buflen; /*!< length of the buffer */ diff --git a/Externals/mbedtls/include/mbedtls/pk.h b/Externals/mbedtls/include/mbedtls/pk.h index f9f9b9bb09..91950f9407 100644 --- a/Externals/mbedtls/include/mbedtls/pk.h +++ b/Externals/mbedtls/include/mbedtls/pk.h @@ -2,7 +2,8 @@ * \file pk.h * * \brief Public Key abstraction layer - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -62,7 +63,10 @@ #define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ #define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ -#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The signature is valid but its length is less than expected. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ #ifdef __cplusplus extern "C" { @@ -85,7 +89,7 @@ typedef enum { * \brief Options for RSASSA-PSS signature verification. * See \c mbedtls_rsa_rsassa_pss_verify_ext() */ -typedef struct +typedef struct mbedtls_pk_rsassa_pss_options { mbedtls_md_type_t mgf1_hash_id; int expected_salt_len; @@ -105,7 +109,7 @@ typedef enum /** * \brief Item to send to the debug module */ -typedef struct +typedef struct mbedtls_pk_debug_item { mbedtls_pk_debug_type type; const char *name; @@ -123,12 +127,26 @@ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; /** * \brief Public key container */ -typedef struct +typedef struct mbedtls_pk_context { - const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ void * pk_ctx; /**< Underlying public key context */ } mbedtls_pk_context; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * rs_ctx; /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + #if defined(MBEDTLS_RSA_C) /** * Quick access to an RSA context inside a PK context. @@ -179,20 +197,45 @@ typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); /** - * \brief Initialize a mbedtls_pk_context (as NONE) + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. */ void mbedtls_pk_init( mbedtls_pk_context *ctx ); /** - * \brief Free a mbedtls_pk_context + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. */ void mbedtls_pk_free( mbedtls_pk_context *ctx ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + /** * \brief Initialize a PK context with the information given * and allocates the type-specific PK subcontext. * - * \param ctx Context to initialize. Must be empty (type NONE). + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). * \param info Information to use * * \return 0 on success, @@ -208,7 +251,8 @@ int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); /** * \brief Initialize an RSA-alt context * - * \param ctx Context to initialize. Must be empty (type NONE). + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). * \param key RSA key pointer * \param decrypt_func Decryption function * \param sign_func Signing function @@ -228,7 +272,7 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, /** * \brief Get the size in bits of the underlying key * - * \param ctx Context to use + * \param ctx The context to query. It must have been initialized. * * \return Key size in bits, or 0 on error */ @@ -236,7 +280,8 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); /** * \brief Get the length in bytes of the underlying key - * \param ctx Context to use + * + * \param ctx The context to query. It must have been initialized. * * \return Key length in bytes, or 0 on error */ @@ -248,18 +293,21 @@ static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) /** * \brief Tell if a context can do the operation given by type * - * \param ctx Context to test - * \param type Target type + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. * - * \return 0 if context can't do the operations, - * 1 otherwise. + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). */ int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); /** * \brief Verify signature (including padding if relevant). * - * \param ctx PK context to use + * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) @@ -267,8 +315,8 @@ int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); * \param sig_len Signature length * * \return 0 on success (signature is valid), - * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than sig_len, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, * or a specific error code. * * \note For RSA keys, the default padding type is PKCS#1 v1.5. @@ -284,13 +332,39 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ); +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ); + /** * \brief Verify signature, with options. * (Includes verification of the padding depending on type.) * * \param type Signature type (inc. possible padding type) to verify * \param options Pointer to type-specific options, or NULL - * \param ctx PK context to use + * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) @@ -298,10 +372,10 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * \param sig_len Signature length * * \return 0 on success (signature is valid), - * MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be * used for this type of signatures, - * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than sig_len, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, * or a specific error code. * * \note If hash_len is 0, then the length associated with md_alg @@ -321,7 +395,8 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, /** * \brief Make signature, including padding if relevant. * - * \param ctx PK context to use - must hold a private key + * \param ctx The PK context to use. It must have been set up + * with a private key. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) @@ -347,10 +422,41 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ); + /** * \brief Decrypt message (including padding if relevant). * - * \param ctx PK context to use - must hold a private key + * \param ctx The PK context to use. It must have been set up + * with a private key. * \param input Input to decrypt * \param ilen Input size * \param output Decrypted output @@ -371,7 +477,7 @@ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, /** * \brief Encrypt message (including padding if relevant). * - * \param ctx PK context to use + * \param ctx The PK context to use. It must have been set up. * \param input Message to encrypt * \param ilen Message size * \param output Encrypted output @@ -402,7 +508,7 @@ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_conte /** * \brief Export debug information * - * \param ctx Context to use + * \param ctx The PK context to use. It must have been initialized. * \param items Place to write debug items * * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA @@ -412,7 +518,7 @@ int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *item /** * \brief Access the type name * - * \param ctx Context to use + * \param ctx The PK context to use. It must have been initialized. * * \return Type name on success, or "invalid PK" */ @@ -421,9 +527,10 @@ const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); /** * \brief Get the key type * - * \param ctx Context to use + * \param ctx The PK context to use. It must have been initialized. * - * \return Type on success, or MBEDTLS_PK_NONE + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. */ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); @@ -432,12 +539,22 @@ mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); /** * \brief Parse a private key in PEM or DER format * - * \param ctx key to be initialized - * \param key input buffer - * \param keylen size of the buffer - * (including the terminating null byte for PEM data) - * \param pwd password for decryption (optional) - * \param pwdlen size of the password + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a @@ -455,10 +572,15 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, /** * \brief Parse a public key in PEM or DER format * - * \param ctx key to be initialized - * \param key input buffer - * \param keylen size of the buffer - * (including the terminating null byte for PEM data) + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a @@ -476,9 +598,14 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, /** * \brief Load and parse a private key * - * \param ctx key to be initialized + * \param ctx The PK context to fill. It must have been initialized + * but not set up. * \param path filename to read the private key from - * \param password password to decrypt the file (can be NULL) + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a @@ -495,7 +622,8 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, /** * \brief Load and parse a public key * - * \param ctx key to be initialized + * \param ctx The PK context to fill. It must have been initialized + * but not set up. * \param path filename to read the public key from * * \note On entry, ctx must be empty, either freshly initialised @@ -518,7 +646,7 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) * return value to determine where you should start * using the buffer * - * \param ctx private to write away + * \param ctx PK context which must contain a valid private key. * \param buf buffer to write to * \param size size of the buffer * @@ -533,7 +661,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_ * return value to determine where you should start * using the buffer * - * \param ctx public key to write away + * \param ctx PK context which must contain a valid public or private key. * \param buf buffer to write to * \param size size of the buffer * @@ -546,9 +674,10 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, si /** * \brief Write a public key to a PEM string * - * \param ctx public key to write away - * \param buf buffer to write to - * \param size size of the buffer + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. * * \return 0 if successful, or a specific error code */ @@ -557,9 +686,10 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, si /** * \brief Write a private key to a PKCS#1 or SEC1 PEM string * - * \param ctx private to write away - * \param buf buffer to write to - * \param size size of the buffer + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. * * \return 0 if successful, or a specific error code */ @@ -578,7 +708,8 @@ int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_ * * \param p the position in the ASN.1 data * \param end end of the buffer - * \param pk the key to fill + * \param pk The PK context to fill. It must have been initialized + * but not set up. * * \return 0 if successful, or a specific PK error code */ @@ -593,7 +724,7 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, * * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) - * \param key public key to write away + * \param key PK context which must contain a valid public or private key. * * \return the length written or a negative error code */ diff --git a/Externals/mbedtls/include/mbedtls/pk_internal.h b/Externals/mbedtls/include/mbedtls/pk_internal.h index 01d0f214bc..48b7a5f7bf 100644 --- a/Externals/mbedtls/include/mbedtls/pk_internal.h +++ b/Externals/mbedtls/include/mbedtls/pk_internal.h @@ -1,8 +1,9 @@ /** - * \file pk.h + * \file pk_internal.h * * \brief Public Key abstraction layer: wrapper functions - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -58,6 +59,21 @@ struct mbedtls_pk_info_t int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + /** Decrypt message */ int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, @@ -79,6 +95,14 @@ struct mbedtls_pk_info_t /** Free the given context */ void (*ctx_free_func)( void *ctx ); +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + /** Interface with the debug module */ void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); diff --git a/Externals/mbedtls/include/mbedtls/pkcs11.h b/Externals/mbedtls/include/mbedtls/pkcs11.h index 2e88928137..02427ddc1e 100644 --- a/Externals/mbedtls/include/mbedtls/pkcs11.h +++ b/Externals/mbedtls/include/mbedtls/pkcs11.h @@ -4,7 +4,8 @@ * \brief Wrapper for PKCS#11 library libpkcs11-helper * * \author Adriaan de Jong - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -49,7 +50,8 @@ extern "C" { /** * Context for PKCS #11 private keys. */ -typedef struct { +typedef struct mbedtls_pkcs11_context +{ pkcs11h_certificate_t pkcs11h_cert; int len; } mbedtls_pkcs11_context; diff --git a/Externals/mbedtls/include/mbedtls/pkcs12.h b/Externals/mbedtls/include/mbedtls/pkcs12.h index 9b2d904591..d441357b7f 100644 --- a/Externals/mbedtls/include/mbedtls/pkcs12.h +++ b/Externals/mbedtls/include/mbedtls/pkcs12.h @@ -2,7 +2,8 @@ * \file pkcs12.h * * \brief PKCS#12 Personal Information Exchange Syntax - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_PKCS12_H #define MBEDTLS_PKCS12_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "md.h" #include "cipher.h" #include "asn1.h" @@ -45,6 +52,8 @@ extern "C" { #endif +#if defined(MBEDTLS_ASN1_PARSE_C) + /** * \brief PKCS12 Password Based function (encryption / decryption) * for pbeWithSHAAnd128BitRC4 @@ -86,6 +95,8 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *input, size_t len, unsigned char *output ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + /** * \brief The PKCS#12 derivation function uses a password and a salt * to produce pseudo-random bits for a particular "purpose". diff --git a/Externals/mbedtls/include/mbedtls/pkcs5.h b/Externals/mbedtls/include/mbedtls/pkcs5.h index ec5cb9e744..c92185f7a6 100644 --- a/Externals/mbedtls/include/mbedtls/pkcs5.h +++ b/Externals/mbedtls/include/mbedtls/pkcs5.h @@ -4,7 +4,8 @@ * \brief PKCS#5 functions * * \author Mathias Olsson - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -25,6 +26,12 @@ #ifndef MBEDTLS_PKCS5_H #define MBEDTLS_PKCS5_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "asn1.h" #include "md.h" @@ -43,6 +50,8 @@ extern "C" { #endif +#if defined(MBEDTLS_ASN1_PARSE_C) + /** * \brief PKCS#5 PBES2 function * @@ -61,6 +70,8 @@ int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *data, size_t datalen, unsigned char *output ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + /** * \brief PKCS#5 PBKDF2 using HMAC * @@ -80,6 +91,8 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p unsigned int iteration_count, uint32_t key_length, unsigned char *output ); +#if defined(MBEDTLS_SELF_TEST) + /** * \brief Checkup routine * @@ -87,6 +100,8 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p */ int mbedtls_pkcs5_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/platform.h b/Externals/mbedtls/include/mbedtls/platform.h index b1b019e55e..89fe8a7b19 100644 --- a/Externals/mbedtls/include/mbedtls/platform.h +++ b/Externals/mbedtls/include/mbedtls/platform.h @@ -1,9 +1,19 @@ /** * \file platform.h * - * \brief mbed TLS Platform abstraction layer + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,7 +28,7 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PLATFORM_H #define MBEDTLS_PLATFORM_H @@ -30,9 +40,12 @@ #endif #if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" +#include "platform_time.h" #endif +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */ + #ifdef __cplusplus extern "C" { #endif @@ -51,34 +64,34 @@ extern "C" { #include #if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) #if defined(_WIN32) -#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< Default snprintf to use */ +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ #else -#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use */ +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ #endif #endif #if !defined(MBEDTLS_PLATFORM_STD_PRINTF) -#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use */ +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) -#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */ +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) -#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use */ +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_FREE) -#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use */ +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT) -#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use */ +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_TIME) -#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use */ +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) -#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< Default exit value to use */ +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) -#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< Default exit value to use */ +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ #endif #if defined(MBEDTLS_FS_IO) #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) @@ -101,7 +114,7 @@ extern "C" { /* \} name SECTION: Module settings */ /* - * The function pointers for calloc and free + * The function pointers for calloc and free. */ #if defined(MBEDTLS_PLATFORM_MEMORY) #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ @@ -111,16 +124,17 @@ extern "C" { #else /* For size_t */ #include -extern void * (*mbedtls_calloc)( size_t n, size_t size ); -extern void (*mbedtls_free)( void *ptr ); +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); /** - * \brief Set your own memory implementation function pointers + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. * - * \param calloc_func the calloc function implementation - * \param free_func the free function implementation + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. * - * \return 0 if successful + * \return \c 0. */ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), void (*free_func)( void * ) ); @@ -139,11 +153,13 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); /** - * \brief Set your own fprintf function pointer + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. * - * \param fprintf_func the fprintf function implementation + * \param fprintf_func The \c fprintf function implementation. * - * \return 0 + * \return \c 0. */ int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, ... ) ); @@ -162,11 +178,13 @@ int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char extern int (*mbedtls_printf)( const char *format, ... ); /** - * \brief Set your own printf function pointer + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. * - * \param printf_func the printf function implementation + * \param printf_func The \c printf function implementation. * - * \return 0 + * \return \c 0 on success. */ int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); #else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ @@ -195,11 +213,12 @@ int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); /** - * \brief Set your own snprintf function pointer + * \brief This function allows configuring a custom + * \c snprintf function pointer. * - * \param snprintf_func the snprintf function implementation + * \param snprintf_func The \c snprintf function implementation. * - * \return 0 + * \return \c 0 on success. */ int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, const char * format, ... ) ); @@ -207,7 +226,7 @@ int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) #define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO #else -#define mbedtls_snprintf snprintf +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF #endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ @@ -218,11 +237,13 @@ int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, extern void (*mbedtls_exit)( int status ); /** - * \brief Set your own exit function pointer + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. * - * \param exit_func the exit function implementation + * \param exit_func The \c exit function implementation. * - * \return 0 + * \return \c 0 on success. */ int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); #else @@ -265,12 +286,13 @@ extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); /** - * \brief Set your own seed file writing/reading functions + * \brief This function allows configuring custom seed file writing and + * reading functions. * - * \param nv_seed_read_func the seed reading function implementation - * \param nv_seed_write_func the seed writing function implementation + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. * - * \return 0 + * \return \c 0 on success. */ int mbedtls_platform_set_nv_seed( int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), @@ -288,6 +310,56 @@ int mbedtls_platform_set_nv_seed( #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct mbedtls_platform_context +{ + char dummy; /**< A placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else +#include "platform_alt.h" +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform-specific initialization + * operations. + * + * \note This function should be called before any other library functions. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/platform_time.h b/Externals/mbedtls/include/mbedtls/platform_time.h index abb3431420..2ed36f56c9 100644 --- a/Externals/mbedtls/include/mbedtls/platform_time.h +++ b/Externals/mbedtls/include/mbedtls/platform_time.h @@ -2,7 +2,8 @@ * \file platform_time.h * * \brief mbed TLS Platform time abstraction - * + */ +/* * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * diff --git a/Externals/mbedtls/include/mbedtls/platform_util.h b/Externals/mbedtls/include/mbedtls/platform_util.h new file mode 100644 index 0000000000..dba6d45982 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/platform_util.h @@ -0,0 +1,185 @@ +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright (C) 2018, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ +#ifndef MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "platform_time.h" +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) + +#if defined(MBEDTLS_PARAM_FAILED) +/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h. + * + * This flag can be used to check whether it is safe to assume that + * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed(). + */ +#define MBEDTLS_PARAM_FAILED_ALT +#else /* MBEDTLS_PARAM_FAILED */ +#define MBEDTLS_PARAM_FAILED( cond ) \ + mbedtls_param_failed( #cond, __FILE__, __LINE__ ) + +/** + * \brief User supplied callback function for parameter validation failure. + * See #MBEDTLS_CHECK_PARAMS for context. + * + * This function will be called unless an alternative treatement + * is defined through the #MBEDTLS_PARAM_FAILED macro. + * + * This function can return, and the operation will be aborted, or + * alternatively, through use of setjmp()/longjmp() can resume + * execution in the application code. + * + * \param failure_condition The assertion that didn't hold. + * \param file The file where the assertion failed. + * \param line The line in the file where the assertion failed. + */ +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ); +#endif /* MBEDTLS_PARAM_FAILED */ + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return( ret ); \ + } \ + } while( 0 ) + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE( cond ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return; \ + } \ + } while( 0 ) + +#else /* MBEDTLS_CHECK_PARAMS */ + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +#endif /* MBEDTLS_CHECK_PARAMS */ + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here + * to avoid conflict with other headers which define and use + * it, too. We might want to move all these definitions here at + * some point for uniformity. */ +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_string_constant_t) ( VAL ) ) +MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) ) +#undef MBEDTLS_DEPRECATED +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/Externals/mbedtls/include/mbedtls/poly1305.h b/Externals/mbedtls/include/mbedtls/poly1305.h new file mode 100644 index 0000000000..f0ec44c968 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/poly1305.h @@ -0,0 +1,192 @@ +/** + * \file poly1305.h + * + * \brief This file contains Poly1305 definitions and functions. + * + * Poly1305 is a one-time message authenticator that can be used to + * authenticate messages. Poly1305-AES was created by Daniel + * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic + * Poly1305 algorithm (not tied to AES) was also standardized in RFC + * 7539. + * + * \author Daniel King + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +#ifndef MBEDTLS_POLY1305_H +#define MBEDTLS_POLY1305_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct mbedtls_poly1305_context +{ + uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t acc[5]; /** The accumulator number. */ + uint8_t queue[16]; /** The current partial block of data. */ + size_t queue_len; /** The number of bytes stored in 'queue'. */ +} +mbedtls_poly1305_context; + +#else /* MBEDTLS_POLY1305_ALT */ +#include "poly1305_alt.h" +#endif /* MBEDTLS_POLY1305_ALT */ + +/** + * \brief This function initializes the specified Poly1305 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by a call to + * \c mbedtls_poly1305_starts(), then one or more calls to + * \c mbedtls_poly1305_update(), then one call to + * \c mbedtls_poly1305_finish(), then finally + * \c mbedtls_poly1305_free(). + * + * \param ctx The Poly1305 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function releases and clears the specified + * Poly1305 context. + * + * \param ctx The Poly1305 context to clear. This may be \c NULL, in which + * case this function is a no-op. If it is not \c NULL, it must + * point to an initialized Poly1305 context. + */ +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function sets the one-time authentication key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param ctx The Poly1305 context to which the key should be bound. + * This must be initialized. + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This functions feeds an input buffer into an ongoing + * Poly1305 computation. + * + * It is called between \c mbedtls_cipher_poly1305_starts() and + * \c mbedtls_cipher_poly1305_finish(). + * It can be called repeatedly to process a stream of data. + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function generates the Poly1305 Message + * Authentication Code (MAC). + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param mac The buffer to where the MAC is written. This must + * be a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function calculates the Poly1305 MAC of the input + * buffer with the provided key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * \param mac The buffer to where the MAC is written. This must be + * a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_poly1305_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_POLY1305_H */ diff --git a/Externals/mbedtls/include/mbedtls/ripemd160.h b/Externals/mbedtls/include/mbedtls/ripemd160.h index 7083fc8599..b42f6d2a95 100644 --- a/Externals/mbedtls/include/mbedtls/ripemd160.h +++ b/Externals/mbedtls/include/mbedtls/ripemd160.h @@ -2,7 +2,8 @@ * \file ripemd160.h * * \brief RIPE MD-160 message digest - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -32,18 +33,22 @@ #include #include -#if !defined(MBEDTLS_RIPEMD160_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + /** * \brief RIPEMD-160 context structure */ -typedef struct +typedef struct mbedtls_ripemd160_context { uint32_t total[2]; /*!< number of bytes processed */ uint32_t state[5]; /*!< intermediate digest state */ @@ -51,6 +56,10 @@ typedef struct } mbedtls_ripemd160_context; +#else /* MBEDTLS_RIPEMD160_ALT */ +#include "ripemd160.h" +#endif /* MBEDTLS_RIPEMD160_ALT */ + /** * \brief Initialize RIPEMD-160 context * @@ -78,51 +87,139 @@ void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, * \brief RIPEMD-160 context setup * * \param ctx context to be initialized + * + * \return 0 if successful */ -void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ); +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ); /** * \brief RIPEMD-160 process buffer * * \param ctx RIPEMD-160 context - * \param input buffer holding the data + * \param input buffer holding the data * \param ilen length of the input data + * + * \return 0 if successful */ -void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, - const unsigned char *input, size_t ilen ); +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); /** * \brief RIPEMD-160 final digest * * \param ctx RIPEMD-160 context * \param output RIPEMD-160 checksum result + * + * \return 0 if successful */ -void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ); +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); -/* Internal use */ -void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned char data[64] ); +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); -#ifdef __cplusplus -} +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED #endif +/** + * \brief RIPEMD-160 context setup + * + * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( + mbedtls_ripemd160_context *ctx ); -#else /* MBEDTLS_RIPEMD160_ALT */ -#include "ripemd160.h" -#endif /* MBEDTLS_RIPEMD160_ALT */ +/** + * \brief RIPEMD-160 process buffer + * + * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( + mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); -#ifdef __cplusplus -extern "C" { -#endif +/** + * \brief RIPEMD-160 final digest + * + * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( + mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( + mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Output = RIPEMD-160( input buffer ) * - * \param input buffer holding the data + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 + * + * \param input buffer holding the data * \param ilen length of the input data * \param output RIPEMD-160 checksum result */ -void mbedtls_ripemd160( const unsigned char *input, size_t ilen, - unsigned char output[20] ); +MBEDTLS_DEPRECATED void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine @@ -131,6 +228,8 @@ void mbedtls_ripemd160( const unsigned char *input, size_t ilen, */ int mbedtls_ripemd160_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/rsa.h b/Externals/mbedtls/include/mbedtls/rsa.h index 35185dfda1..906c427332 100644 --- a/Externals/mbedtls/include/mbedtls/rsa.h +++ b/Externals/mbedtls/include/mbedtls/rsa.h @@ -1,9 +1,16 @@ /** * \file rsa.h * - * \brief The RSA public-key cryptosystem + * \brief This file provides an API for the RSA public-key cryptosystem. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The RSA public-key cryptosystem is defined in Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption + * and Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,7 +25,7 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_RSA_H #define MBEDTLS_RSA_H @@ -42,24 +49,31 @@ #define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ #define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ -#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the library's validity check. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the validity check of the library. */ #define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ #define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ #define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ #define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ #define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ +/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used. + */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ + +/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ + /* * RSA constants */ -#define MBEDTLS_RSA_PUBLIC 0 -#define MBEDTLS_RSA_PRIVATE 1 +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ -#define MBEDTLS_RSA_PKCS_V15 0 -#define MBEDTLS_RSA_PKCS_V21 1 +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ -#define MBEDTLS_RSA_SIGN 1 -#define MBEDTLS_RSA_CRYPT 2 +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ #define MBEDTLS_RSA_SALT_LEN_ANY -1 @@ -67,168 +81,489 @@ * The above constants may be used even if the RSA module is compile out, * eg for alternative (PKCS#11) RSA implemenations in the PK layers. */ -#if defined(MBEDTLS_RSA_C) #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + /** - * \brief RSA context structure + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. */ -typedef struct +typedef struct mbedtls_rsa_context { - int ver; /*!< always 0 */ - size_t len; /*!< size(N) in chars */ + int ver; /*!< Always 0.*/ + size_t len; /*!< The size of \p N in Bytes. */ - mbedtls_mpi N; /*!< public modulus */ - mbedtls_mpi E; /*!< public exponent */ + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ - mbedtls_mpi D; /*!< private exponent */ - mbedtls_mpi P; /*!< 1st prime factor */ - mbedtls_mpi Q; /*!< 2nd prime factor */ - mbedtls_mpi DP; /*!< D % (P - 1) */ - mbedtls_mpi DQ; /*!< D % (Q - 1) */ - mbedtls_mpi QP; /*!< 1 / (Q % P) */ + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ - mbedtls_mpi RN; /*!< cached R^2 mod N */ - mbedtls_mpi RP; /*!< cached R^2 mod P */ - mbedtls_mpi RQ; /*!< cached R^2 mod Q */ + mbedtls_mpi DP; /*!< D % (P - 1). */ + mbedtls_mpi DQ; /*!< D % (Q - 1). */ + mbedtls_mpi QP; /*!< 1 / (Q % P). */ - mbedtls_mpi Vi; /*!< cached blinding value */ - mbedtls_mpi Vf; /*!< cached un-blinding value */ + mbedtls_mpi RN; /*!< cached R^2 mod N. */ - int padding; /*!< MBEDTLS_RSA_PKCS_V15 for 1.5 padding and - MBEDTLS_RSA_PKCS_v21 for OAEP/PSS */ - int hash_id; /*!< Hash identifier of mbedtls_md_type_t as - specified in the mbedtls_md.h header file - for the EME-OAEP and EMSA-PSS - encoding */ + mbedtls_mpi RP; /*!< cached R^2 mod P. */ + mbedtls_mpi RQ; /*!< cached R^2 mod Q. */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ #if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex */ + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ #endif } mbedtls_rsa_context; +#else /* MBEDTLS_RSA_ALT */ +#include "rsa_alt.h" +#endif /* MBEDTLS_RSA_ALT */ + /** - * \brief Initialize an RSA context + * \brief This function initializes an RSA context. * - * Note: Set padding to MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP * encryption scheme and the RSASSA-PSS signature scheme. * - * \param ctx RSA context to be initialized - * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 - * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. * - * \note The hash_id parameter is actually ignored - * when using MBEDTLS_RSA_PKCS_V15 padding. - * - * \note Choice of padding mode is strictly enforced for private key + * \note The choice of padding mode is strictly enforced for private key * operations, since there might be security concerns in - * mixing padding modes. For public key operations it's merely + * mixing padding modes. For public key operations it is * a default value, which can be overriden by calling specific - * rsa_rsaes_xxx or rsa_rsassa_xxx functions. + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. * - * \note The chosen hash is always used for OEAP encryption. - * For PSS signatures, it's always used for making signatures, - * but can be overriden (and always is, if set to - * MBEDTLS_MD_NONE) for verifying them. + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overriden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overriden. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of ::mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. It is unused + * otherwise. */ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, - int padding, - int hash_id); + int padding, + int hash_id ); /** - * \brief Set padding for an already initialized RSA context - * See \c mbedtls_rsa_init() for details. + * \brief This function imports a set of core parameters into an + * RSA context. * - * \param ctx RSA context to be set - * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 - * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param D The private exponent. This may be \c NULL. + * \param E The public exponent. This may be \c NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. */ -void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id); +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); /** - * \brief Generate an RSA keypair + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. * - * \param ctx RSA context that will hold the key - * \param f_rng RNG function - * \param p_rng RNG parameter - * \param nbits size of the public key in bits - * \param exponent public exponent (e.g., 65537) + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. * - * \note mbedtls_rsa_init() must be called beforehand to setup - * the RSA context. + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. + * \param D The private exponent. This may be \c NULL. + * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. + * \param E The public exponent. This may be \c NULL. + * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus. + * This may be \c NULL if this field need not be exported. + * \param P The MPI to hold the first prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param Q The MPI to hold the second prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param D The MPI to hold the private exponent. + * This may be \c NULL if this field need not be exported. + * \param E The MPI to hold the public exponent. + * This may be \c NULL if this field need not be exported. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, + * or \c NULL if this field need not be exported. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, + * or \c NULL if this field need not be exported. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, + * or \c NULL if this field need not be exported. + * \param E_len The size of the buffer for the public exponent. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold \c D modulo `P-1`, + * or \c NULL if it need not be exported. + * \param DQ The MPI to hold \c D modulo `Q-1`, + * or \c NULL if it need not be exported. + * \param QP The MPI to hold modular inverse of \c Q modulo \c P, + * or \c NULL if it need not be exported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The initialized RSA context to be configured. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \param ctx The initialized RSA context used to hold the key. + * \param f_rng The RNG function to be used for key generation. + * This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't need a context. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent to use. For example, \c 65537. + * This must be odd and greater than \c 1. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ); + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); /** - * \brief Check a public RSA key + * \brief This function checks if a context contains at least an RSA + * public key. * - * \param ctx RSA context to be checked + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code */ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); /** - * \brief Check a private RSA key + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. * - * \param ctx RSA context to be checked + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); /** - * \brief Check a public-private RSA key pair. - * Check each of the contexts, and make sure they match. + * \brief This function checks a public-private RSA key pair. * - * \param pub RSA context holding the public key - * \param prv RSA context holding the private key + * It checks each of the contexts, and makes sure they match. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \param pub The initialized RSA context holding the public key. + * \param prv The initialized RSA context holding the private key. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ -int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ); +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); /** - * \brief Do an RSA public key operation + * \brief This function performs an RSA public key operation. * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer + * \param ctx The initialized RSA context to use. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \note This function does not handle message padding. * - * \note This function does NOT take care of message - * padding. Also, be sure to set input[0] = 0 or assure that - * input is smaller than N. + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output ); /** - * \brief Do an RSA private key operation + * \brief This function performs an RSA private key operation. * - * \param ctx RSA context - * \param f_rng RNG function (Needed for blinding) - * \param p_rng RNG parameter - * \param input input buffer - * \param output output buffer + * \note Blinding is used if and only if a PRNG is provided. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function, used for blinding. It is discouraged + * and deprecated to pass \c NULL here, in which case + * blinding will be omitted. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or if \p f_rng doesn't need a context. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). */ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -237,23 +572,42 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, unsigned char *output ); /** - * \brief Generic wrapper to perform a PKCS#1 encryption using the - * mode from the context. Add the message padding, then do an - * RSA operation. + * \brief This function adds the message padding, then performs an RSA + * operation. * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding - * and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is mandatory for PKCS#1 v2.1 padding + * encoding, and for PKCS#1 v1.5 padding encoding when used + * with \p mode set to #MBEDTLS_RSA_PUBLIC. For PKCS#1 v1.5 + * padding encoding and \p mode set to #MBEDTLS_RSA_PRIVATE, + * it is used for blinding and should be provided in this + * case; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng is \c NULL or if \p f_rng doesn't + * need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -263,20 +617,37 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, unsigned char *output ); /** - * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is needed for padding generation + * if \p mode is #MBEDTLS_RSA_PUBLIC. If \p mode is + * #MBEDTLS_RSA_PRIVATE (discouraged), it is used for + * blinding and should be provided; see mbedtls_rsa_private(). + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng is \c NULL or if \p f_rng + * doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -286,23 +657,41 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, unsigned char *output ); /** - * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding - * and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param label buffer holding the custom label to use - * \param label_len contains the label length - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initnialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and must be provided. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param ilen The length of the plaintext buffer \p input in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. This must not be \c NULL. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -314,24 +703,48 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, unsigned char *output ); /** - * \brief Generic wrapper to perform a PKCS#1 decryption using the - * mode from the context. Do an RSA operation, then remove - * the message padding + * \brief This function performs an RSA operation, then removes the + * message padding. * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -342,22 +755,46 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, size_t output_max_len ); /** - * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. */ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -368,24 +805,50 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, size_t output_max_len ); /** - * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param label buffer holding the custom label to use - * \param label_len contains the label length - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -398,28 +861,53 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, size_t output_max_len ); /** - * \brief Generic wrapper to perform a PKCS#1 signature using the - * mode from the context. Do a private RSA operation to sign - * a message digest + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for - * MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. * - * \note In case of PKCS#1 v2.1 encoding, see comments on - * \note \c mbedtls_rsa_rsassa_pss_sign() for details on md_alg and hash_id. + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. If the padding mode is PKCS#1 v2.1, + * this must be provided. If the padding mode is PKCS#1 v1.5 and + * \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding + * and should be provided; see mbedtls_rsa_private() for more + * more. It is ignored otherwise. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -431,22 +919,42 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, unsigned char *sig ); /** - * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -458,28 +966,56 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, unsigned char *sig ); /** - * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for - * MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code + * \note This function always uses the maximum possible salt size, + * up to the length of the payload hash. This choice of salt + * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 + * v2.2) §9.1.1 step 3. Furthermore this function enforces a + * minimum salt size which is the hash size minus 2 bytes. If + * this minimum size is too large given the key size (the salt + * size, plus the hash size, plus 2 bytes must be no more than + * the key size in bytes), this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. * - * \note The hash_id in the RSA context is the one used for the - * encoding. md_alg in the function call is the type of hash - * that is encoded. According to RFC 3447 it is advised to - * keep both hashes the same. + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -491,27 +1027,48 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, unsigned char *sig ); /** - * \brief Generic wrapper to perform a PKCS#1 verification using the - * mode from the context. Do a public RSA operation and check - * the message digest + * \brief This function performs a public RSA operation and checks + * the message digest. * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. * - * \note In case of PKCS#1 v2.1 encoding, see comments on - * \c mbedtls_rsa_rsassa_pss_verify() about md_alg and hash_id. + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -523,22 +1080,41 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, const unsigned char *sig ); /** - * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -550,29 +1126,52 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, const unsigned char *sig ); /** - * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) - * (This is the "simple" version.) + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext + * The hash function for the MGF mask generating function + * is that specified in the RSA context. * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p md_alg from the function call is used. * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. * - * \note The hash_id in the RSA context is the one used for the - * verification. md_alg in the function call is the type of - * hash that is verified. According to RFC 3447 it is advised to - * keep both hashes the same. If hash_id in the RSA context is - * unset, the md_alg from the function call is used. + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -584,28 +1183,43 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, const unsigned char *sig ); /** - * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) - * (This is the version with "full" options.) + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param mgf1_hash_id message digest used for mask generation - * \param expected_salt_len Length of the salt used in padding, use - * MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length - * \param sig buffer holding the ciphertext + * The hash function for the MGF mask generating function + * is that specified in \p mgf1_hash_id. * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). + * \note The \p hash_id in the RSA context is ignored. * - * \note The hash_id in the RSA context is ignored. + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -619,34 +1233,39 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, const unsigned char *sig ); /** - * \brief Copy the components of an RSA context + * \brief This function copies the components of an RSA context. * - * \param dst Destination context - * \param src Source context + * \param dst The destination context. This must be initialized. + * \param src The source context. This must be initialized. * - * \return 0 on success, - * MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. */ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); /** - * \brief Free the components of an RSA key + * \brief This function frees the components of an RSA key. * - * \param ctx RSA Context to free + * \param ctx The RSA context to free. May be \c NULL, in which case + * this function is a no-op. If it is not \c NULL, it must + * point to an initialized RSA context. */ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); +#if defined(MBEDTLS_SELF_TEST) + /** - * \brief Checkup routine + * \brief The RSA checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_rsa_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif -#endif /* MBEDTLS_RSA_C */ - #endif /* rsa.h */ diff --git a/Externals/mbedtls/include/mbedtls/rsa_internal.h b/Externals/mbedtls/include/mbedtls/rsa_internal.h new file mode 100644 index 0000000000..53abd3c5b0 --- /dev/null +++ b/Externals/mbedtls/include/mbedtls/rsa_internal.h @@ -0,0 +1,226 @@ +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * + */ +/* + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa_internal.h */ diff --git a/Externals/mbedtls/include/mbedtls/sha1.h b/Externals/mbedtls/include/mbedtls/sha1.h index 7a67c6c1fb..bb6ecf05a4 100644 --- a/Externals/mbedtls/include/mbedtls/sha1.h +++ b/Externals/mbedtls/include/mbedtls/sha1.h @@ -1,9 +1,17 @@ /** * \file sha1.h * - * \brief SHA-1 cryptographic hash function + * \brief This file contains SHA-1 definitions and functions. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,7 +26,7 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA1_H #define MBEDTLS_SHA1_H @@ -32,103 +40,311 @@ #include #include -#if !defined(MBEDTLS_SHA1_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 /**< SHA-1 input data was malformed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + /** - * \brief SHA-1 context structure + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * */ -typedef struct +typedef struct mbedtls_sha1_context { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ } mbedtls_sha1_context; -/** - * \brief Initialize SHA-1 context - * - * \param ctx SHA-1 context to be initialized - */ -void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); - -/** - * \brief Clear SHA-1 context - * - * \param ctx SHA-1 context to be cleared - */ -void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-1 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha1_clone( mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src ); - -/** - * \brief SHA-1 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); - -/** - * \brief SHA-1 process buffer - * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-1 final digest - * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); - -/* Internal use */ -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - #else /* MBEDTLS_SHA1_ALT */ #include "sha1_alt.h" #endif /* MBEDTLS_SHA1_ALT */ -#ifdef __cplusplus -extern "C" { -#endif - /** - * \brief Output = SHA-1( input buffer ) + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-1 checksum result */ -void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); /** - * \brief Checkup routine + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized. + * \param data The data block being processed. + * This must be a readable buffer of length \c 64 bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of size \c 20 Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. * - * \return 0 if successful, or 1 if the test failed */ int mbedtls_sha1_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/sha256.h b/Externals/mbedtls/include/mbedtls/sha256.h index f8041adf08..d64739820c 100644 --- a/Externals/mbedtls/include/mbedtls/sha256.h +++ b/Externals/mbedtls/include/mbedtls/sha256.h @@ -1,9 +1,13 @@ /** * \file sha256.h * - * \brief SHA-224 and SHA-256 cryptographic hash function + * \brief This file contains SHA-224 and SHA-256 definitions and functions. * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,7 +22,7 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA256_H #define MBEDTLS_SHA256_H @@ -32,108 +36,260 @@ #include #include -#if !defined(MBEDTLS_SHA256_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + /** - * \brief SHA-256 context structure + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). */ -typedef struct +typedef struct mbedtls_sha256_context { - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[8]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - int is224; /*!< 0 => SHA-256, else SHA-224 */ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ } mbedtls_sha256_context; -/** - * \brief Initialize SHA-256 context - * - * \param ctx SHA-256 context to be initialized - */ -void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); - -/** - * \brief Clear SHA-256 context - * - * \param ctx SHA-256 context to be cleared - */ -void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-256 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha256_clone( mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src ); - -/** - * \brief SHA-256 context setup - * - * \param ctx context to be initialized - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); - -/** - * \brief SHA-256 process buffer - * - * \param ctx SHA-256 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-256 final digest - * - * \param ctx SHA-256 context - * \param output SHA-224/256 checksum result - */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); - -/* Internal use */ -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - #else /* MBEDTLS_SHA256_ALT */ #include "sha256_alt.h" #endif /* MBEDTLS_SHA256_ALT */ -#ifdef __cplusplus -extern "C" { +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The context to use. This must be initialized. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to use. This must be + * initialized and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must + * be a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED #endif /** - * \brief Output = SHA-256( input buffer ) + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-224/256 checksum result - * \param is224 0 = use SHA256, 1 = use SHA224 + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be either + * \c 0 for SHA-256, or \c 1 for SHA-224. */ -void mbedtls_sha256( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ); +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) /** - * \brief Checkup routine + * \brief The SHA-224 and SHA-256 checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_sha256_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/sha512.h b/Externals/mbedtls/include/mbedtls/sha512.h index 627694f425..c06ceed1d1 100644 --- a/Externals/mbedtls/include/mbedtls/sha512.h +++ b/Externals/mbedtls/include/mbedtls/sha512.h @@ -1,9 +1,12 @@ /** * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. * - * \brief SHA-384 and SHA-512 cryptographic hash function - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,7 +21,7 @@ * 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) + * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA512_H #define MBEDTLS_SHA512_H @@ -32,107 +35,263 @@ #include #include -#if !defined(MBEDTLS_SHA512_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 /**< SHA-512 input data was malformed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + /** - * \brief SHA-512 context structure + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). */ -typedef struct +typedef struct mbedtls_sha512_context { - uint64_t total[2]; /*!< number of bytes processed */ - uint64_t state[8]; /*!< intermediate digest state */ - unsigned char buffer[128]; /*!< data block being processed */ - int is384; /*!< 0 => SHA-512, else SHA-384 */ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ + int is384; /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ } mbedtls_sha512_context; -/** - * \brief Initialize SHA-512 context - * - * \param ctx SHA-512 context to be initialized - */ -void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); - -/** - * \brief Clear SHA-512 context - * - * \param ctx SHA-512 context to be cleared - */ -void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-512 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha512_clone( mbedtls_sha512_context *dst, - const mbedtls_sha512_context *src ); - -/** - * \brief SHA-512 context setup - * - * \param ctx context to be initialized - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); - -/** - * \brief SHA-512 process buffer - * - * \param ctx SHA-512 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-512 final digest - * - * \param ctx SHA-512 context - * \param output SHA-384/512 checksum result - */ -void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ); - -#ifdef __cplusplus -} -#endif - #else /* MBEDTLS_SHA512_ALT */ #include "sha512_alt.h" #endif /* MBEDTLS_SHA512_ALT */ -#ifdef __cplusplus -extern "C" { +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must point to an initialized + * SHA-512 context. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be + * either \c for SHA-512, or \c 1 for SHA-384. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. This function is for + * internal use only. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This + * must be a readable buffer of length \c 128 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512 or \c 1 for SHA-384. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of length \c 128 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. This must be + * a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED #endif /** - * \brief Output = SHA-512( input buffer ) + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-384/512 checksum result - * \param is384 0 = use SHA512, 1 = use SHA384 + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. This must be a + * readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. */ -void mbedtls_sha512( const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ); +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); -/** - * \brief Checkup routine +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + + /** + * \brief The SHA-384 or SHA-512 checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 on success. + * \return \c 1 on failure. */ int mbedtls_sha512_self_test( int verbose ); - -/* Internal use */ -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); +#endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } diff --git a/Externals/mbedtls/include/mbedtls/ssl.h b/Externals/mbedtls/include/mbedtls/ssl.h index ba499d2bde..8106bb4ab0 100644 --- a/Externals/mbedtls/include/mbedtls/ssl.h +++ b/Externals/mbedtls/include/mbedtls/ssl.h @@ -2,7 +2,8 @@ * \file ssl.h * * \brief SSL/TLS functions. - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -48,11 +49,20 @@ #endif #if defined(MBEDTLS_ZLIB_SUPPORT) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and will be removed in the next major revision of the library" +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and cannot be used if MBEDTLS_DEPRECATED_REMOVED is set" +#endif + #include "zlib.h" #endif #if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" +#include "platform_time.h" #endif /* @@ -102,13 +112,17 @@ #define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ #define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ #define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ -#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< No data of requested type currently available on underlying transport. */ #define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ #define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ #define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ #define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ +#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */ +#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ +#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */ /* * Various constants @@ -185,6 +199,9 @@ #define MBEDTLS_SSL_PRESET_DEFAULT 0 #define MBEDTLS_SSL_PRESET_SUITEB 2 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + /* * Default range for DTLS retransmission timer value, in milliseconds. * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. @@ -205,7 +222,7 @@ #endif /* - * Maxium fragment length in bytes, + * Maximum fragment length in bytes, * determines the size of each of the two internal I/O buffers. * * Note: the RFC defines the default size of SSL / TLS messages. If you @@ -219,6 +236,22 @@ #define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ #endif +#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) +#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +/* + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + */ +#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) +#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 +#endif + /* \} name SECTION: Module settings */ /* @@ -522,7 +555,6 @@ typedef void mbedtls_ssl_set_timer_t( void * ctx, */ typedef int mbedtls_ssl_get_timer_t( void * ctx ); - /* Defined below */ typedef struct mbedtls_ssl_session mbedtls_ssl_session; typedef struct mbedtls_ssl_context mbedtls_ssl_context; @@ -531,6 +563,7 @@ typedef struct mbedtls_ssl_config mbedtls_ssl_config; /* Defined in ssl_internal.h */ typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; #if defined(MBEDTLS_X509_CRT_PARSE_C) typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; #endif @@ -538,6 +571,218 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; #endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Callback type: start external signature operation. + * + * This callback is called during an SSL handshake to start + * a signature decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p hash if the value + * is needed for later processing, because the \p hash buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \note For RSA signatures, this function must produce output + * that is consistent with PKCS#1 v1.5 in the same way as + * mbedtls_rsa_pkcs1_sign(). Before the private key operation, + * apply the padding steps described in RFC 8017, section 9.2 + * "EMSA-PKCS1-v1_5" as follows. + * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the DigestInfo to be + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 3, with `T = hash` and `tLen = hash_len`. + * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the hash to be encoded and + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 2, with `digestAlgorithm` obtained by calling + * mbedtls_oid_get_oid_by_md() on \p md_alg. + * + * \note For ECDSA signatures, the output format is the DER encoding + * `Ecdsa-Sig-Value` defined in + * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param md_alg Hash algorithm. + * \param hash Buffer containing the hash. This buffer is + * no longer valid when the function returns. + * \param hash_len Size of the \c hash buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ); + +/** + * \brief Callback type: start external decryption operation. + * + * This callback is called during an SSL handshake to start + * an RSA decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p input if the value + * is needed for later processing, because the \p input buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \warning RSA decryption as used in TLS is subject to a potential + * timing side channel attack first discovered by Bleichenbacher + * in 1998. This attack can be remotely exploitable + * in practice. To avoid this attack, you must ensure that + * if the callback performs an RSA decryption, the time it + * takes to execute and return the result does not depend + * on whether the RSA decryption succeeded or reported + * invalid padding. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param input Buffer containing the input ciphertext. This buffer + * is no longer valid when the function returns. + * \param input_len Size of the \p input buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Callback type: resume external operation. + * + * This callback is called during an SSL handshake to resume + * an external operation started by the + * ::mbedtls_ssl_async_sign_t or + * ::mbedtls_ssl_async_decrypt_t callback. + * + * This function typically checks the status of a pending + * request or causes the request queue to make progress, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * It may call mbedtls_ssl_set_async_operation_data() to modify + * this context. + * + * Note that when this function returns a status other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any + * resources associated with the operation. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param output Buffer containing the output (signature or decrypted + * data) on success. + * \param output_len On success, number of bytes written to \p output. + * \param output_size Size of the \p output buffer in bytes. + * + * \return 0 if output of the operation is available in the + * \p output buffer. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * is still in progress. Subsequent requests for progress + * on the SSL connection will call the resume callback + * again. + * \return Any other error means that the operation is aborted. + * The SSL handshake is aborted. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ); + +/** + * \brief Callback type: cancel external operation. + * + * This callback is called if an SSL connection is closed + * while an asynchronous operation is in progress. Note that + * this callback is not called if the + * ::mbedtls_ssl_async_resume_t callback has run and has + * returned a value other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case + * the asynchronous operation has already completed. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * + * \param ssl The SSL connection instance. It should not be + * modified. + */ +typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /* * This structure is used for storing current session data. */ @@ -654,6 +899,16 @@ struct mbedtls_ssl_config mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */ + void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) const int *sig_hashes; /*!< allowed signature hashes */ #endif @@ -668,10 +923,18 @@ struct mbedtls_ssl_config #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char *psk; /*!< pre-shared key */ - size_t psk_len; /*!< length of the pre-shared key */ - unsigned char *psk_identity; /*!< identity for PSK negotiation */ - size_t psk_identity_len;/*!< length of identity */ + unsigned char *psk; /*!< pre-shared key. This field should + only be set via + mbedtls_ssl_conf_psk() */ + size_t psk_len; /*!< length of the pre-shared key. This + field should only be set via + mbedtls_ssl_conf_psk() */ + unsigned char *psk_identity; /*!< identity for PSK negotiation. This + field should only be set via + mbedtls_ssl_conf_psk() */ + size_t psk_identity_len;/*!< length of identity. This field should + only be set via + mbedtls_ssl_conf_psk() */ #endif #if defined(MBEDTLS_SSL_ALPN) @@ -749,6 +1012,10 @@ struct mbedtls_ssl_config #if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) unsigned int fallback : 1; /*!< is this a fallback? */ #endif +#if defined(MBEDTLS_SSL_SRV_C) + unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in + Certificate Request messages? */ +#endif }; @@ -765,14 +1032,14 @@ struct mbedtls_ssl_context int renego_records_seen; /*!< Records since renego request, or with DTLS, number of retransmissions of request if renego_max_records is < 0 */ -#endif +#endif /* MBEDTLS_SSL_RENEGOTIATION */ int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) unsigned badmac_seen; /*!< records with a bad MAC received */ -#endif +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ @@ -828,16 +1095,23 @@ struct mbedtls_ssl_context uint16_t in_epoch; /*!< DTLS epoch for incoming records */ size_t next_record_offset; /*!< offset of the next record in datagram (equal to in_left if none) */ -#endif +#endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) uint64_t in_window_top; /*!< last validated record seq_num */ uint64_t in_window; /*!< bitmask for replay detection */ -#endif +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ size_t in_hslen; /*!< current handshake message length, including the handshake header */ int nb_zero; /*!< # of 0-length encrypted messages */ - int record_read; /*!< record is already present */ + + int keep_current_message; /*!< drop or reuse current message + on next call to record layer? */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t disable_datagram_packing; /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Record layer (outgoing data) @@ -853,12 +1127,18 @@ struct mbedtls_ssl_context size_t out_msglen; /*!< record header: message length */ size_t out_left; /*!< amount of data not yet written */ + unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + #if defined(MBEDTLS_ZLIB_SUPPORT) unsigned char *compress_buf; /*!< zlib data buffer */ -#endif +#endif /* MBEDTLS_ZLIB_SUPPORT */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) signed char split_done; /*!< current record already splitted? */ -#endif +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ /* * PKI layer @@ -871,11 +1151,11 @@ struct mbedtls_ssl_context #if defined(MBEDTLS_X509_CRT_PARSE_C) char *hostname; /*!< expected peer CN for verification (and SNI if available) */ -#endif +#endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ALPN) const char *alpn_chosen; /*!< negotiated protocol */ -#endif +#endif /* MBEDTLS_SSL_ALPN */ /* * Information for DTLS hello verify @@ -883,7 +1163,7 @@ struct mbedtls_ssl_context #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) unsigned char *cli_id; /*!< transport-level ID of the client */ size_t cli_id_len; /*!< length of cli_id */ -#endif +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ /* * Secure renegotiation @@ -895,7 +1175,7 @@ struct mbedtls_ssl_context size_t verify_data_len; /*!< length of verify data stored */ char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ -#endif +#endif /* MBEDTLS_SSL_RENEGOTIATION */ }; #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) @@ -917,14 +1197,6 @@ extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl); extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ -/** - * \brief Returns the list of ciphersuites supported by the SSL/TLS module. - * - * \return a statically allocated array of ciphersuites, the last - * entry is 0. - */ -const int *mbedtls_ssl_list_ciphersuites( void ); - /** * \brief Return the name of the ciphersuite associated with the * given ID @@ -960,8 +1232,13 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); * \note No copy of the configuration context is made, it can be * shared by many mbedtls_ssl_context structures. * - * \warning Modifying the conf structure after it has been used in this - * function is unsupported! + * \warning The conf structure will be accessed during the session. + * It must not be modified or freed as long as the session + * is active. + * + * \warning This function must be called exactly once per context. + * Calling mbedtls_ssl_setup again is not supported, even + * if no session is active. * * \param ssl SSL context * \param conf SSL configuration to use @@ -1042,7 +1319,7 @@ void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); * * If set, the verify callback is called for each * certificate in the chain. For implementation - * information, please see \c x509parse_verify() + * information, please see \c mbedtls_x509_crt_verify() * * \param conf SSL configuration * \param f_vrfy verification function @@ -1118,6 +1395,52 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, mbedtls_ssl_recv_t *f_recv, mbedtls_ssl_recv_timeout_t *f_recv_timeout ); +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/** + * \brief Set the Maximum Tranport Unit (MTU). + * Special value: 0 means unset (no limit). + * This represents the maximum size of a datagram payload + * handled by the transport layer (usually UDP) as determined + * by the network link and stack. In practice, this controls + * the maximum size datagram the DTLS layer will pass to the + * \c f_send() callback set using \c mbedtls_ssl_set_bio(). + * + * \note The limit on datagram size is converted to a limit on + * record payload by subtracting the current overhead of + * encapsulation and encryption/authentication if any. + * + * \note This can be called at any point during the connection, for + * example when a Path Maximum Transfer Unit (PMTU) + * estimate becomes available from other sources, + * such as lower (or higher) protocol layers. + * + * \note This setting only controls the size of the packets we send, + * and does not restrict the size of the datagrams we're + * willing to receive. Client-side, you can request the + * server to use smaller records with \c + * mbedtls_ssl_conf_max_frag_len(). + * + * \note If both a MTU and a maximum fragment length have been + * configured (or negotiated with the peer), the resulting + * lower limit on record payload (see first note) is used. + * + * \note This can only be used to decrease the maximum size + * of datagrams (hence records, see first note) sent. It + * cannot be used to increase the maximum size of records over + * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN. + * + * \note Values lower than the current record layer expansion will + * result in an error when trying to send data. + * + * \note Using record compression together with a non-zero MTU value + * will result in an error when trying to send data. + * + * \param ssl SSL context + * \param mtu Value of the path MTU in bytes + */ +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /** * \brief Set the timeout period for mbedtls_ssl_read() * (Default: no timeout.) @@ -1146,7 +1469,7 @@ void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) * * \note See the documentation of \c mbedtls_ssl_set_timer_t and * \c mbedtls_ssl_get_timer_t for the conventions this pair of - * callbacks must fallow. + * callbacks must follow. * * \note On some platforms, timing.c provides * \c mbedtls_timing_set_delay() and @@ -1281,6 +1604,85 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, void *p_export_keys ); #endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +/** + * \brief Configure asynchronous private key operation callbacks. + * + * \param conf SSL configuration context + * \param f_async_sign Callback to start a signature operation. See + * the description of ::mbedtls_ssl_async_sign_t + * for more information. This may be \c NULL if the + * external processor does not support any signature + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_decrypt Callback to start a decryption operation. See + * the description of ::mbedtls_ssl_async_decrypt_t + * for more information. This may be \c NULL if the + * external processor does not support any decryption + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_resume Callback to resume an asynchronous operation. See + * the description of ::mbedtls_ssl_async_resume_t + * for more information. This may not be \c NULL unless + * \p f_async_sign and \p f_async_decrypt are both + * \c NULL. + * \param f_async_cancel Callback to cancel an asynchronous operation. See + * the description of ::mbedtls_ssl_async_cancel_t + * for more information. This may be \c NULL if + * no cleanup is needed. + * \param config_data A pointer to configuration data which can be + * retrieved with + * mbedtls_ssl_conf_get_async_config_data(). The + * library stores this value without dereferencing it. + */ +void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *config_data ); + +/** + * \brief Retrieve the configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + * + * \param conf SSL configuration context + * \return The configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + */ +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * + * \return The asynchronous operation user context that was last + * set during the current handshake. If + * mbedtls_ssl_set_async_operation_data() has not yet been + * called during the current handshake, this function returns + * \c NULL. + */ +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * \param ctx The new value of the asynchronous operation user context. + * Call mbedtls_ssl_get_async_operation_data() later during the + * same handshake to retrieve this value. + */ +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /** * \brief Callback type: generate a cookie * @@ -1422,6 +1824,38 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_DTLS) + +/** + * \brief Allow or disallow packing of multiple handshake records + * within a single datagram. + * + * \param ssl The SSL context to configure. + * \param allow_packing This determines whether datagram packing may + * be used or not. A value of \c 0 means that every + * record will be sent in a separate datagram; a + * value of \c 1 means that, if space permits, + * multiple handshake messages (including CCS) belonging to + * a single flight may be packed within a single datagram. + * + * \note This is enabled by default and should only be disabled + * for test purposes, or if datagram packing causes + * interoperability issues with peers that don't support it. + * + * \note Allowing datagram packing reduces the network load since + * there's less overhead if multiple messages share the same + * datagram. Also, it increases the handshake efficiency + * since messages belonging to a single datagram will not + * be reordered in transit, and so future message buffering + * or flight retransmission (if no buffering is used) as + * means to deal with reordering are needed less frequently. + * + * \note Application records are not affected by this option and + * are currently always sent in separate datagrams. + * + */ +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ); + /** * \brief Set retransmit timeout values for the DTLS handshake. * (DTLS only, no effect on TLS.) @@ -1576,6 +2010,10 @@ void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, /** * \brief Set the data required to verify peer certificate * + * \note See \c mbedtls_x509_crt_verify() for notes regarding the + * parameters ca_chain (maps to trust_ca for that function) + * and ca_crl. + * * \param conf SSL configuration * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) * \param ca_crl trusted CA CRLs @@ -1606,6 +2044,14 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, * whether it matches those preferences - the server can then * decide what it wants to do with it. * + * \note The provided \p pk_key needs to match the public key in the + * first certificate in \p own_cert, or all handshakes using + * that certificate will fail. It is your responsibility + * to ensure that; this function will not perform any check. + * You may use mbedtls_pk_check_pair() in order to perform + * this check yourself, but be aware that this function can + * be computationally expensive on some key types. + * * \param conf SSL configuration * \param own_cert own public certificate chain * \param pk_key own private key @@ -1689,18 +2135,50 @@ void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + /** * \brief Set the Diffie-Hellman public P and G values, * read as hexadecimal strings (server-side only) - * (Default: MBEDTLS_DHM_RFC5114_MODP_2048_[PG]) + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]) * * \param conf SSL configuration * \param dhm_P Diffie-Hellman-Merkle modulus * \param dhm_G Diffie-Hellman-Merkle generator * + * \deprecated Superseded by \c mbedtls_ssl_conf_dh_param_bin. + * * \return 0 if successful */ -int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ); +MBEDTLS_DEPRECATED int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, + const char *dhm_P, + const char *dhm_G ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the Diffie-Hellman public P and G values + * from big-endian binary presentations. + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form + * \param P_len Length of DHM modulus + * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form + * \param G_len Length of DHM generator + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ); /** * \brief Set the Diffie-Hellman public P and G values, @@ -1784,15 +2262,22 @@ void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, #if defined(MBEDTLS_X509_CRT_PARSE_C) /** - * \brief Set the hostname to check against the received server - * certificate. It sets the ServerName TLS extension too, - * if the extension is enabled. - * (client-side only) + * \brief Set or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, + * too, if that extension is enabled. (client-side only) * * \param ssl SSL context - * \param hostname the server hostname + * \param hostname the server hostname, may be NULL to clear hostname + + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * too long input hostname. + * + * Hostname set to the one provided on success (cleared + * when NULL). On allocation failure hostname is cleared. + * On too long input failure, old hostname is unchanged. */ int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); #endif /* MBEDTLS_X509_CRT_PARSE_C */ @@ -2031,15 +2516,42 @@ void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); #endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Set the maximum fragment length to emit and/or negotiate - * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) + * (Default: the smaller of MBEDTLS_SSL_IN_CONTENT_LEN and + * MBEDTLS_SSL_OUT_CONTENT_LEN, usually 2^14 bytes) * (Server: set maximum fragment length to emit, * usually negotiated by the client during handshake * (Client: set maximum fragment length to emit *and* * negotiate with the server during handshake) * + * \note With TLS, this currently only affects ApplicationData (sent + * with \c mbedtls_ssl_read()), not handshake messages. + * With DTLS, this affects both ApplicationData and handshake. + * + * \note This sets the maximum length for a record's payload, + * excluding record overhead that will be added to it, see + * \c mbedtls_ssl_get_record_expansion(). + * + * \note For DTLS, it is also possible to set a limit for the total + * size of daragrams passed to the transport layer, including + * record overhead, see \c mbedtls_ssl_set_mtu(). + * * \param conf SSL configuration * \param mfl_code Code for maximum fragment length (allowed values: * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, @@ -2183,7 +2695,7 @@ void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_ /** * \brief Set record counter threshold for periodic renegotiation. - * (Default: 2^64 - 256.) + * (Default: 2^48 - 1) * * Renegotiation is automatically triggered when a record * counter (outgoing or ingoing) crosses the defined @@ -2194,33 +2706,90 @@ void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_ * Lower values can be used to enforce policies such as "keys * must be refreshed every N packets with cipher X". * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * * \param conf SSL configuration * \param period The threshold value: a big-endian 64-bit number. - * Set to 2^64 - 1 to disable periodic renegotiation */ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, const unsigned char period[8] ); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** - * \brief Return the number of data bytes available to read + * \brief Check if there is data already read from the + * underlying transport but not yet processed. * * \param ssl SSL context * - * \return how many bytes are available in the read buffer + * \return 0 if nothing's pending, 1 otherwise. + * + * \note This is different in purpose and behaviour from + * \c mbedtls_ssl_get_bytes_avail in that it considers + * any kind of unprocessed data, not only unread + * application data. If \c mbedtls_ssl_get_bytes + * returns a non-zero value, this function will + * also signal pending data, but the converse does + * not hold. For example, in DTLS there might be + * further records waiting to be processed from + * the current underlying transport's datagram. + * + * \note If this function returns 1 (data pending), this + * does not imply that a subsequent call to + * \c mbedtls_ssl_read will provide any data; + * e.g., the unprocessed data might turn out + * to be an alert or a handshake message. + * + * \note This function is useful in the following situation: + * If the SSL/TLS module successfully returns from an + * operation - e.g. a handshake or an application record + * read - and you're awaiting incoming data next, you + * must not immediately idle on the underlying transport + * to have data ready, but you need to check the value + * of this function first. The reason is that the desired + * data might already be read but not yet processed. + * If, in contrast, a previous call to the SSL/TLS module + * returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary + * to call this function, as the latter error code entails + * that all internal data has been processed. + * + */ +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the number of application data bytes + * remaining to be read from the current record. + * + * \param ssl SSL context + * + * \return How many bytes are available in the application + * data record read buffer. + * + * \note When working over a datagram transport, this is + * useful to detect the current datagram's boundary + * in case \c mbedtls_ssl_read has written the maximal + * amount of data fitting into the input buffer. + * */ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); /** * \brief Return the result of the certificate verification * - * \param ssl SSL context + * \param ssl The SSL context to use. * - * \return 0 if successful, - * -1 if result is not available (eg because the handshake was - * aborted too early), or - * a combination of BADCERT_xxx and BADCRL_xxx flags, see - * x509.h + * \return \c 0 if the certificate verification was successful. + * \return \c -1u if the result is not available. This may happen + * e.g. if the handshake aborts early, or a verification + * callback returned a fatal error. + * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX + * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. */ uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); @@ -2246,6 +2815,9 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); * \brief Return the (maximum) number of bytes added by the record * layer: header + encryption/MAC overhead (inc. padding) * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * * \param ssl SSL context * * \return Current maximum record expansion in bytes, or @@ -2260,12 +2832,8 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); * This is the value negotiated with peer if any, * or the locally configured value. * - * \note With DTLS, \c mbedtls_ssl_write() will return an error if - * called with a larger length value. - * With TLS, \c mbedtls_ssl_write() will fragment the input if - * necessary and return the number of bytes written; it is up - * to the caller to call \c mbedtls_ssl_write() again in - * order to send the remaining bytes if any. + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_record_payload() * * \param ssl SSL context * @@ -2274,6 +2842,34 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +/** + * \brief Return the current maximum outgoing record payload in bytes. + * This takes into account the config.h setting \c + * MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated + * max fragment length extension if used, and for DTLS the + * path MTU as configured and current record expansion. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * + * \sa mbedtls_ssl_set_mtu() + * \sa mbedtls_ssl_get_max_frag_len() + * \sa mbedtls_ssl_get_record_expansion() + * + * \param ssl SSL context + * + * \return Current maximum payload for an outgoing record, + * or a negative error code. + */ +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ); + #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Return the peer certificate from the current connection @@ -2297,7 +2893,6 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss * \brief Save session in order to resume it later (client-side only) * Session data is copied to presented session structure. * - * \warning Currently, peer certificate is lost in the operation. * * \param ssl SSL context * \param session session context @@ -2305,7 +2900,18 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss * \return 0 if successful, * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid + * arguments are otherwise invalid. + * + * \note Only the server certificate is copied, and not the full chain, + * so you should not attempt to validate the certificate again + * by calling \c mbedtls_x509_crt_verify() on it. + * Instead, you should use the results from the verification + * in the original handshake by calling \c mbedtls_ssl_get_verify_result() + * after loading the session again into a new SSL context + * using \c mbedtls_ssl_set_session(). + * + * \note Once the session object is not needed anymore, you should + * free it by calling \c mbedtls_ssl_session_free(). * * \sa mbedtls_ssl_set_session() */ @@ -2317,21 +2923,50 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * * \param ssl SSL context * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or - * a specific SSL error code. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use + * and the client did not demonstrate reachability yet - in + * this case you must stop using the context (see below). + * \return Another SSL error code - in this case you must stop using + * the context (see below). * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * \warning If this function returns something other than + * \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. * * \note If DTLS is in use, then you may choose to handle - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging * purposes, as it is an expected return value rather than an * actual error, but you still need to reset/free the context. + * + * \note Remarks regarding event-driven DTLS: + * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. This is not true for a successful handshake, + * in which case the datagram of the underlying transport that is + * currently being processed might or might not contain further + * DTLS records. */ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); @@ -2339,20 +2974,21 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); * \brief Perform a single step of the SSL handshake * * \note The state of the context (ssl->state) will be at - * the next state after execution of this function. Do not + * the next state after this function returns \c 0. Do not * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * * \param ssl SSL context * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * a specific SSL error code. + * \return See mbedtls_ssl_handshake(). + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. */ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); @@ -2367,13 +3003,18 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); * \param ssl SSL context * * \return 0 if successful, or any mbedtls_ssl_handshake() return - * value. + * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't + * happen during a renegotiation. + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. */ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -2385,32 +3026,68 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * \param buf buffer that will hold the data * \param len maximum number of bytes to read * - * \return the number of bytes read, or - * 0 for EOF, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or - * another negative error code. + * \return The (positive) number of bytes read if successful. + * \return \c 0 if the read end of the underlying transport was closed + * - in this case you must stop using the context (see below). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server + * side of a DTLS connection and the client is initiating a + * new connection using the same source port. See below. + * \return Another SSL error code - in this case you must stop using + * the context (see below). * - * \note If this function returns something other than a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * \warning If this function returns something other than + * a positive value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. * - * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT * (which can only happen server-side), it means that a client * is initiating a new connection using the same source port. * You can either treat that as a connection close and wait * for the client to resend a ClientHello, or directly * continue with \c mbedtls_ssl_handshake() with the same - * context (as it has beeen reset internally). Either way, you - * should make sure this is seen by the application as a new + * context (as it has been reset internally). Either way, you + * must make sure this is seen by the application as a new * connection: application state, if any, should be reset, and * most importantly the identity of the client must be checked * again. WARNING: not validating the identity of the client * again, or not transmitting the new identity to the * application layer, would allow authentication bypass! + * + * \note Remarks regarding event-driven DTLS: + * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. + * - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was + * initially available on the underlying transport, as this data may have + * been only e.g. duplicated messages or a renegotiation request. + * Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even + * when reacting to an incoming-data event from the underlying transport. + * - On success, the datagram of the underlying transport that is currently + * being processed may contain further DTLS records. You should call + * \c mbedtls_ssl_check_pending to check for remaining records. + * */ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); @@ -2427,19 +3104,41 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * \param buf buffer holding the data * \param len how many bytes must be written * - * \return the number of bytes actually written (may be less than len), - * or MBEDTLS_ERR_SSL_WANT_WRITE of MBEDTLS_ERR_SSL_WANT_READ, - * or another negative error code. + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return Another SSL error code - in this case you must stop using + * the context (see below). * - * \note If this function returns something other than a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * \warning If this function returns something other than + * a non-negative value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. * - * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, - * until it returns a positive value. + * until it returns a value greater that or equal to 0. When + * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be + * some partial data in the output buffer, however this is not + * yet sent. * * \note If the requested length is greater than the maximum * fragment length (either the built-in limit or the one set @@ -2448,6 +3147,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. * \c mbedtls_ssl_get_max_frag_len() may be used to query the * active maximum fragment length. + * + * \note Attempting to write 0 bytes will result in an empty TLS + * application record being sent. */ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); @@ -2462,10 +3164,10 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_ * \return 0 if successful, or a specific SSL error code. * * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. */ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, unsigned char level, @@ -2478,10 +3180,10 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, * \return 0 if successful, or a specific SSL error code. * * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. */ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); @@ -2513,7 +3215,6 @@ void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS * \param preset a MBEDTLS_SSL_PRESET_XXX value - * (currently unused). * * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. * @@ -2541,6 +3242,9 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); * \brief Free referenced items in an SSL session including the * peer certificate and clear memory * + * \note A session object can be freed even if the SSL context + * that was used to retrieve the session is still in use. + * * \param session SSL session */ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); diff --git a/Externals/mbedtls/include/mbedtls/ssl_cache.h b/Externals/mbedtls/include/mbedtls/ssl_cache.h index 3734bb7274..52ba0948c5 100644 --- a/Externals/mbedtls/include/mbedtls/ssl_cache.h +++ b/Externals/mbedtls/include/mbedtls/ssl_cache.h @@ -2,7 +2,8 @@ * \file ssl_cache.h * * \brief SSL session cache implementation - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_SSL_CACHE_H #define MBEDTLS_SSL_CACHE_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ssl.h" #if defined(MBEDTLS_THREADING_C) diff --git a/Externals/mbedtls/include/mbedtls/ssl_ciphersuites.h b/Externals/mbedtls/include/mbedtls/ssl_ciphersuites.h index deaaa37515..71053e5ba7 100644 --- a/Externals/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ b/Externals/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -2,7 +2,8 @@ * \file ssl_ciphersuites.h * * \brief SSL Ciphersuites for mbed TLS - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_SSL_CIPHERSUITES_H #define MBEDTLS_SSL_CIPHERSUITES_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "pk.h" #include "cipher.h" #include "md.h" @@ -168,6 +175,45 @@ extern "C" { #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ + #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ @@ -231,6 +277,15 @@ extern "C" { #define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ +/* RFC 7905 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ + /* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below */ @@ -260,6 +315,47 @@ typedef enum { #define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED #endif +/* Key exchanges allowing client certificate requests */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED +#endif + +/* Key exchanges involving server signature in ServerKeyExchange */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED +#endif + +/* Key exchanges using ECDH */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED +#endif + +/* Key exchanges that don't involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED +#endif + +/* Key exchanges that involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED +#endif + /* Key exchanges using a PSK */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ @@ -268,7 +364,13 @@ typedef enum { #define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED #endif -/* Key exchanges using a ECDHE */ +/* Key exchanges using DHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED +#endif + +/* Key exchanges using ECDHE */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) @@ -309,11 +411,128 @@ const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuit #if defined(MBEDTLS_PK_C) mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); #endif int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/ssl_cookie.h b/Externals/mbedtls/include/mbedtls/ssl_cookie.h index 037e1c3112..e34760ae85 100644 --- a/Externals/mbedtls/include/mbedtls/ssl_cookie.h +++ b/Externals/mbedtls/include/mbedtls/ssl_cookie.h @@ -2,7 +2,8 @@ * \file ssl_cookie.h * * \brief DTLS cookie callbacks implementation - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_SSL_COOKIE_H #define MBEDTLS_SSL_COOKIE_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ssl.h" #if defined(MBEDTLS_THREADING_C) @@ -49,7 +56,7 @@ extern "C" { /** * \brief Context for the default cookie functions. */ -typedef struct +typedef struct mbedtls_ssl_cookie_ctx { mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ #if !defined(MBEDTLS_HAVE_TIME) diff --git a/Externals/mbedtls/include/mbedtls/ssl_internal.h b/Externals/mbedtls/include/mbedtls/ssl_internal.h index 668c0f567c..bd5ad94dbf 100644 --- a/Externals/mbedtls/include/mbedtls/ssl_internal.h +++ b/Externals/mbedtls/include/mbedtls/ssl_internal.h @@ -1,8 +1,9 @@ /** - * \file ssl_ticket.h + * \file ssl_internal.h * * \brief Internal functions shared by the SSL modules - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,7 +24,14 @@ #ifndef MBEDTLS_SSL_INTERNAL_H #define MBEDTLS_SSL_INTERNAL_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + #include "ssl.h" +#include "cipher.h" #if defined(MBEDTLS_MD5_C) #include "md5.h" @@ -69,6 +77,9 @@ #endif /* MBEDTLS_SSL_PROTO_TLS1 */ #endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + /* Determine maximum supported version */ #define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 @@ -88,6 +99,14 @@ #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +/* Shorthand for restartable ECC */ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_SSL__ECP_RESTARTABLE +#endif + #define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 #define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ #define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ @@ -138,12 +157,76 @@ #define MBEDTLS_SSL_PADDING_ADD 0 #endif -#define MBEDTLS_SSL_BUFFER_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ - + MBEDTLS_SSL_COMPRESSION_ADD \ - + 29 /* counter + header + IV */ \ - + MBEDTLS_SSL_MAC_ADD \ - + MBEDTLS_SSL_PADDING_ADD \ - ) +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \ + MBEDTLS_MAX_IV_LENGTH + \ + MBEDTLS_SSL_MAC_ADD + \ + MBEDTLS_SSL_PADDING_ADD \ + ) + +#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_IN_CONTENT_LEN ) ) + +#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_OUT_CONTENT_LEN ) ) + +/* The maximum number of buffered handshake messages. */ +#define MBEDTLS_SSL_MAX_BUFFERED_HS 4 + +/* Maximum length we can advertise as our max content length for + RFC 6066 max_fragment_length extension negotiation purposes + (the lesser of both sizes, if they are unequal.) + */ +#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ + (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ + ? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \ + : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \ + ) + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 +#error "Bad configuration - record content too large." +#endif + +#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." +#endif + +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - outgoing protected record payload too large." +#endif + +/* Calculate buffer sizes */ + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) ) + +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) ) + +#ifdef MBEDTLS_ZLIB_SUPPORT +/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */ +#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \ + ( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN ) \ + ? MBEDTLS_SSL_IN_BUFFER_LEN \ + : MBEDTLS_SSL_OUT_BUFFER_LEN \ + ) +#endif /* * TLS extension flags (for extensions with outgoing ServerHello content @@ -157,6 +240,24 @@ extern "C" { #endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) +/* + * Abstraction for a grid of allowed signature-hash-algorithm pairs. + */ +struct mbedtls_ssl_sig_hash_set_t +{ + /* At the moment, we only need to remember a single suitable + * hash algorithm per signature algorithm. As long as that's + * the case - and we don't need a general lookup function - + * we can implement the sig-hash-set as a map from signatures + * to hash algorithms. */ + mbedtls_md_type_t rsa; + mbedtls_md_type_t ecdsa; +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + /* * This structure contains the parameters only needed during handshake. */ @@ -165,8 +266,11 @@ struct mbedtls_ssl_handshake_params /* * Handshake specific crypto variables */ - int sig_alg; /*!< Hash algorithm for signature */ - int verify_sig_alg; /*!< Signature algorithm for verify */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ +#endif #if defined(MBEDTLS_DHM_C) mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ #endif @@ -179,7 +283,7 @@ struct mbedtls_ssl_handshake_params unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ size_t ecjpake_cache_len; /*!< Length of cached data */ #endif -#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ @@ -195,8 +299,20 @@ struct mbedtls_ssl_handshake_params mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ -#endif +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + int ecrs_enabled; /*!< Handshake supports EC restart? */ + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ + enum { /* this complements ssl->state with info on intra-state operations */ + ssl_ecrs_none = 0, /*!< nothing going on (yet) */ + ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ + ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ + ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ + } ecrs_state; /*!< current (or last) operation */ + size_t ecrs_n; /*!< place for saving a length */ +#endif #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ @@ -206,19 +322,46 @@ struct mbedtls_ssl_handshake_params unsigned char verify_cookie_len; /*!< Cli: cookie length Srv: flag for sending a cookie */ - unsigned char *hs_msg; /*!< Reassembled handshake message */ - uint32_t retransmit_timeout; /*!< Current value of timeout */ unsigned char retransmit_state; /*!< Retransmission state */ - mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ - mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned char *cur_msg_p; /*!< Position in current message */ unsigned int in_flight_start_seq; /*!< Minimum message sequence in the flight being received */ mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for resending messages */ unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter for resending messages */ -#endif + + struct + { + size_t total_bytes_buffered; /*!< Cumulative size of heap allocated + * buffers used for message buffering. */ + + uint8_t seen_ccs; /*!< Indicates if a CCS message has + * been seen in the current flight. */ + + struct mbedtls_ssl_hs_buffer + { + unsigned is_valid : 1; + unsigned is_fragmented : 1; + unsigned is_complete : 1; + unsigned char *data; + size_t data_len; + } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; + + struct + { + unsigned char *data; + size_t len; + unsigned epoch; + } future_record; + + } buffering; + + uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Checksum contexts @@ -261,8 +404,23 @@ struct mbedtls_ssl_handshake_params #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) int extended_ms; /*!< use Extended Master Secret? */ #endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /** Asynchronous operation context. This field is meant for use by the + * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, + * mbedtls_ssl_config::f_async_decrypt_start, + * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). + * The library does not use it internally. */ + void *user_async_ctx; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ }; +typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; + /* * This structure contains a full set of runtime transform parameters * either in negotiation or active. @@ -329,6 +487,28 @@ struct mbedtls_ssl_flight_item }; #endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ); +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ); +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ); + +/* Setup an empty signature-hash set */ +static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) +{ + mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ /** * \brief Free referenced items in an SSL transform context and clear @@ -342,9 +522,9 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); * \brief Free referenced items in an SSL handshake context and clear * memory * - * \param handshake SSL handshake context + * \param ssl SSL context */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); @@ -355,15 +535,92 @@ int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ); int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl The SSL context to use. + * \param update_hs_digest This indicates if the handshake digest + * should be automatically updated in case + * a handshake message is found. + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ); int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ); int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); @@ -384,6 +641,7 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch #if defined(MBEDTLS_PK_C) unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); #endif @@ -471,6 +729,7 @@ static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ); #endif /* Visible for testing purposes only */ @@ -483,16 +742,39 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) { size_t i; - const unsigned char *A = (const unsigned char *) a; - const unsigned char *B = (const unsigned char *) b; - unsigned char diff = 0; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; for( i = 0; i < n; i++ ) - diff |= A[i] ^ B[i]; + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } return( diff ); } +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ); +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/include/mbedtls/ssl_ticket.h b/Externals/mbedtls/include/mbedtls/ssl_ticket.h index 7c6bc61bfb..a84e7816e4 100644 --- a/Externals/mbedtls/include/mbedtls/ssl_ticket.h +++ b/Externals/mbedtls/include/mbedtls/ssl_ticket.h @@ -2,7 +2,8 @@ * \file ssl_ticket.h * * \brief TLS server ticket callbacks implementation - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -23,6 +24,12 @@ #ifndef MBEDTLS_SSL_TICKET_H #define MBEDTLS_SSL_TICKET_H +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + /* * This implementation of the session ticket callbacks includes key * management, rotating the keys periodically in order to preserve forward @@ -43,7 +50,7 @@ extern "C" { /** * \brief Information for session ticket protection */ -typedef struct +typedef struct mbedtls_ssl_ticket_key { unsigned char name[4]; /*!< random key identifier */ uint32_t generation_time; /*!< key generation timestamp (seconds) */ @@ -54,7 +61,7 @@ mbedtls_ssl_ticket_key; /** * \brief Context for session ticket handling functions */ -typedef struct +typedef struct mbedtls_ssl_ticket_context { mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ unsigned char active; /*!< index of the currently active key */ diff --git a/Externals/mbedtls/include/mbedtls/threading.h b/Externals/mbedtls/include/mbedtls/threading.h index b0c34ecc74..92e6e6b987 100644 --- a/Externals/mbedtls/include/mbedtls/threading.h +++ b/Externals/mbedtls/include/mbedtls/threading.h @@ -2,7 +2,8 @@ * \file threading.h * * \brief Threading abstraction layer - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -35,13 +36,16 @@ extern "C" { #endif +/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ #define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ + #define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ #define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ #if defined(MBEDTLS_THREADING_PTHREAD) #include -typedef struct +typedef struct mbedtls_threading_mutex_t { pthread_mutex_t mutex; char is_valid; @@ -95,8 +99,20 @@ extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); /* * Global mutexes */ +#if defined(MBEDTLS_FS_IO) extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +/* This mutex may or may not be used in the default definition of + * mbedtls_platform_gmtime_r(), but in order to determine that, + * we need to check POSIX features, hence modify _POSIX_C_SOURCE. + * With the current approach, this declaration is orphaned, lacking + * an accompanying definition, in case mbedtls_platform_gmtime_r() + * doesn't need it, but that's not a problem. */ extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + #endif /* MBEDTLS_THREADING_C */ #ifdef __cplusplus diff --git a/Externals/mbedtls/include/mbedtls/timing.h b/Externals/mbedtls/include/mbedtls/timing.h index ae7a713e7a..a965fe0d35 100644 --- a/Externals/mbedtls/include/mbedtls/timing.h +++ b/Externals/mbedtls/include/mbedtls/timing.h @@ -1,8 +1,9 @@ /** * \file timing.h * - * \brief Portable interface to the CPU cycle counter - * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -29,16 +30,16 @@ #include MBEDTLS_CONFIG_FILE #endif -#if !defined(MBEDTLS_TIMING_ALT) -// Regular implementation -// - #include #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + /** * \brief timer structure */ @@ -50,13 +51,17 @@ struct mbedtls_timing_hr_time /** * \brief Context for mbedtls_timing_set/get_delay() */ -typedef struct +typedef struct mbedtls_timing_delay_context { struct mbedtls_timing_hr_time timer; uint32_t int_ms; uint32_t fin_ms; } mbedtls_timing_delay_context; +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + extern volatile int mbedtls_timing_alarmed; /** @@ -65,6 +70,9 @@ extern volatile int mbedtls_timing_alarmed; * \warning This is only a best effort! Do not rely on this! * In particular, it is known to be unreliable on virtual * machines. + * + * \note This value starts at an unspecified origin and + * may wrap around. */ unsigned long mbedtls_timing_hardclock( void ); @@ -72,7 +80,18 @@ unsigned long mbedtls_timing_hardclock( void ); * \brief Return the elapsed time in milliseconds * * \param val points to a timer structure - * \param reset if set to 1, the timer is restarted + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. */ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); @@ -80,6 +99,7 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int * \brief Setup an alarm clock * * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * (must be >=0) * * \warning Only one alarm at a time is supported. In a threaded * context, this means one for the whole process, not one per @@ -91,11 +111,15 @@ void mbedtls_set_alarm( int seconds ); * \brief Set a pair of delays to watch * (See \c mbedtls_timing_get_delay().) * - * \param data Pointer to timing data + * \param data Pointer to timing data. * Must point to a valid \c mbedtls_timing_delay_context struct. * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. * \param fin_ms Second (final) delay in milliseconds. * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. */ void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); @@ -106,25 +130,13 @@ void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); * \param data Pointer to timing data * Must point to a valid \c mbedtls_timing_delay_context struct. * - * \return -1 if cancelled (fin_ms = 0) + * \return -1 if cancelled (fin_ms = 0), * 0 if none of the delays are passed, * 1 if only the intermediate delay is passed, * 2 if the final delay is passed. */ int mbedtls_timing_get_delay( void *data ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_TIMING_ALT */ -#include "timing_alt.h" -#endif /* MBEDTLS_TIMING_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine diff --git a/Externals/mbedtls/include/mbedtls/version.h b/Externals/mbedtls/include/mbedtls/version.h index 3270346301..cc736e1590 100644 --- a/Externals/mbedtls/include/mbedtls/version.h +++ b/Externals/mbedtls/include/mbedtls/version.h @@ -2,7 +2,8 @@ * \file version.h * * \brief Run-time version information - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -38,7 +39,7 @@ * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 4 +#define MBEDTLS_VERSION_MINOR 16 #define MBEDTLS_VERSION_PATCH 1 /** @@ -46,9 +47,9 @@ * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02040100 -#define MBEDTLS_VERSION_STRING "2.4.1" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.4.1" +#define MBEDTLS_VERSION_NUMBER 0x02100100 +#define MBEDTLS_VERSION_STRING "2.16.1" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.1" #if defined(MBEDTLS_VERSION_C) diff --git a/Externals/mbedtls/include/mbedtls/x509.h b/Externals/mbedtls/include/mbedtls/x509.h index 54dac166b4..9ae825c183 100644 --- a/Externals/mbedtls/include/mbedtls/x509.h +++ b/Externals/mbedtls/include/mbedtls/x509.h @@ -2,7 +2,8 @@ * \file x509.h * * \brief X.509 generic defines and structures - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -76,6 +77,7 @@ #define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ #define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ #define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */ /* \} name */ /** @@ -157,7 +159,7 @@ #define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) #define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) -#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) /* Parsed (and then ?) */ +#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) /* * Storage format identifiers @@ -246,12 +248,12 @@ int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *se * \note Intended usage is "if( is_past( valid_to ) ) ERROR". * Hence the return value of 1 if on internal errors. * - * \param time mbedtls_x509_time to check + * \param to mbedtls_x509_time to check * * \return 1 if the given time is in the past or an error occured, * 0 otherwise. */ -int mbedtls_x509_time_is_past( const mbedtls_x509_time *time ); +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); /** * \brief Check a given mbedtls_x509_time against the system time @@ -260,12 +262,14 @@ int mbedtls_x509_time_is_past( const mbedtls_x509_time *time ); * \note Intended usage is "if( is_future( valid_from ) ) ERROR". * Hence the return value of 1 if on internal errors. * - * \param time mbedtls_x509_time to check + * \param from mbedtls_x509_time to check * * \return 1 if the given time is in the future or an error occured, * 0 otherwise. */ -int mbedtls_x509_time_is_future( const mbedtls_x509_time *time ); +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine @@ -274,6 +278,8 @@ int mbedtls_x509_time_is_future( const mbedtls_x509_time *time ); */ int mbedtls_x509_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + /* * Internal module functions. You probably do not want to use these unless you * know you do. @@ -294,7 +300,7 @@ int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x50 mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, void **sig_opts ); int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, - mbedtls_x509_time *time ); + mbedtls_x509_time *t ); int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *serial ); int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, diff --git a/Externals/mbedtls/include/mbedtls/x509_crl.h b/Externals/mbedtls/include/mbedtls/x509_crl.h index 7988439900..08a4283a67 100644 --- a/Externals/mbedtls/include/mbedtls/x509_crl.h +++ b/Externals/mbedtls/include/mbedtls/x509_crl.h @@ -2,7 +2,8 @@ * \file x509_crl.h * * \brief X.509 certificate revocation list parsing - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * diff --git a/Externals/mbedtls/include/mbedtls/x509_crt.h b/Externals/mbedtls/include/mbedtls/x509_crt.h index 383e484f71..3dd5922486 100644 --- a/Externals/mbedtls/include/mbedtls/x509_crt.h +++ b/Externals/mbedtls/include/mbedtls/x509_crt.h @@ -2,7 +2,8 @@ * \file x509_crt.h * * \brief X.509 certificate parsing and writing - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -104,7 +105,7 @@ mbedtls_x509_crt; * * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). */ -typedef struct +typedef struct mbedtls_x509_crt_profile { uint32_t allowed_mds; /**< MDs for signatures */ uint32_t allowed_pks; /**< PK algs for signatures */ @@ -142,6 +143,63 @@ typedef struct mbedtls_x509write_cert } mbedtls_x509write_cert; +/** + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} mbedtls_x509_crt_verify_chain_item; + +/** + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/** + * Verification chain as built by \c mbedtls_crt_verify_chain() + */ +typedef struct +{ + mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + unsigned len; +} mbedtls_x509_crt_verify_chain; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Context for resuming X.509 verify operations + */ +typedef struct +{ + /* for check_signature() */ + mbedtls_pk_restart_ctx pk; + + /* for find_parent_in() */ + mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ + mbedtls_x509_crt *fallback_parent; + int fallback_signature_is_good; + + /* for find_parent() */ + int parent_is_trusted; /* -1 if find_parent is not in progress */ + + /* for verify_chain() */ + enum { + x509_crt_rs_none, + x509_crt_rs_find_parent, + } in_progress; /* none if no operation is in progress */ + int self_cnt; + mbedtls_x509_crt_verify_chain ver_chain; + +} mbedtls_x509_crt_restart_ctx; + +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_x509_crt_restart_ctx; + +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * Default security profile. Should provide a good balance between security @@ -174,19 +232,34 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu size_t buflen ); /** - * \brief Parse one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. + * \brief Parse one DER-encoded or one or more concatenated PEM-encoded + * certificates and add them to the chained list. * - * \param chain points to the start of the chain - * \param buf buffer holding the certificate data in PEM or DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) + * For CRTs in PEM encoding, the function parses permissively: + * if at least one certificate can be parsed, the function + * returns the number of certificates for which parsing failed + * (hence \c 0 if all certificates were parsed successfully). + * If no certificate could be parsed, the function returns + * the first (negative) error encountered during parsing. + * + * PEM encoded certificates may be interleaved by other data + * such as human readable descriptions of their content, as + * long as the certificates are enclosed in the PEM specific + * '-----{BEGIN/END} CERTIFICATE-----' delimiters. + * + * \param chain The chain to which to add the parsed certificates. + * \param buf The buffer holding the certificate data in PEM or DER format. + * For certificates in PEM encoding, this may be a concatenation + * of multiple certificates; for DER encoding, the buffer must + * comprise exactly one certificate. + * \param buflen The size of \p buf, including the terminating \c NULL byte + * in case of PEM encoded data. + * + * \return \c 0 if all certificates were parsed successfully. + * \return The (positive) number of certificates that couldn't + * be parsed if parsing was partly successful (see above). + * \return A negative X509 or PEM error code otherwise. * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code */ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); @@ -267,7 +340,13 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, * * All flags left after returning from the callback * are also returned to the application. The function should - * return 0 for anything but a fatal error. + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. * * \note In case verification failed, the results can be displayed * using \c mbedtls_x509_crt_verify_info() @@ -280,8 +359,15 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, * used to sign the certificate, CRL verification is skipped * silently, that is *without* setting any flag. * + * \note The \c trust_ca list can contain two types of certificates: + * (1) those of trusted root CAs, so that certificates + * chaining up to those CAs will be trusted, and (2) + * self-signed end-entity certificates to be trusted (for + * specific peers you know) - in that case, the self-signed + * certificate doesn't need to have the CA bit set. + * * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs + * \param trust_ca the list of trusted CAs (see note above) * \param ca_crl the list of CRLs for trusted CAs (see note above) * \param cn expected Common Name (can be set to * NULL if the CN must not be verified) @@ -289,12 +375,13 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, * \param f_vrfy verification function * \param p_vrfy verification parameter * - * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED - * in which case *flags will have one or more - * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags - * set, - * or another error in case of a fatal error encountered - * during the verification process. + * \return 0 (and flags set to 0) if the chain was verified and valid, + * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified + * but found to be invalid, in which case *flags will have one + * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX + * flags set, or another error (and flags set to 0xffffffff) + * in case of a fatal error encountered during the + * verification process. */ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -338,6 +425,37 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ); +/** + * \brief Restartable version of \c mbedtls_crt_verify_with_profile() + * + * \note Performs the same job as \c mbedtls_crt_verify_with_profile() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * \param rs_ctx restart context (NULL to disable restart) + * + * \return See \c mbedtls_crt_verify_with_profile(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ); + #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) /** * \brief Check usage of certificate against keyUsage extension. @@ -366,21 +484,22 @@ int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, #if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) /** - * \brief Check usage of certificate against extentedJeyUsage. + * \brief Check usage of certificate against extendedKeyUsage. * - * \param crt Leaf certificate used. - * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or MBEDTLS_OID_CLIENT_AUTH). + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or + * MBEDTLS_OID_CLIENT_AUTH). * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). * - * \return 0 if this use of the certificate is allowed, - * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. * - * \note Usually only makes sense on leaf certificates. + * \note Usually only makes sense on leaf certificates. */ int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, - const char *usage_oid, - size_t usage_len ); -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) */ + const char *usage_oid, + size_t usage_len ); +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ #if defined(MBEDTLS_X509_CRL_PARSE_C) /** @@ -408,6 +527,18 @@ void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); * \param crt Certificate chain to free */ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* \} name */ diff --git a/Externals/mbedtls/include/mbedtls/x509_csr.h b/Externals/mbedtls/include/mbedtls/x509_csr.h index fe9843cb54..a3c28048e0 100644 --- a/Externals/mbedtls/include/mbedtls/x509_csr.h +++ b/Externals/mbedtls/include/mbedtls/x509_csr.h @@ -2,7 +2,8 @@ * \file x509_csr.h * * \brief X.509 certificate signing request parsing and writing - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -204,6 +205,14 @@ void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_ty * \param key_usage key usage flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note The decipherOnly flag from the Key Usage + * extension is represented by bit 8 (i.e. + * 0x8000), which cannot typically be represented + * in an unsigned char. Therefore, the flag + * decipherOnly (i.e. + * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this + * function. */ int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); diff --git a/Externals/mbedtls/include/mbedtls/xtea.h b/Externals/mbedtls/include/mbedtls/xtea.h index b073f84efa..b47f553508 100644 --- a/Externals/mbedtls/include/mbedtls/xtea.h +++ b/Externals/mbedtls/include/mbedtls/xtea.h @@ -2,7 +2,8 @@ * \file xtea.h * * \brief XTEA block cipher (32-bit) - * + */ +/* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * @@ -37,23 +38,30 @@ #define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ -#if !defined(MBEDTLS_XTEA_ALT) -// Regular implementation -// +/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ #ifdef __cplusplus extern "C" { #endif +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + /** * \brief XTEA context structure */ -typedef struct +typedef struct mbedtls_xtea_context { uint32_t k[4]; /*!< key */ } mbedtls_xtea_context; +#else /* MBEDTLS_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* MBEDTLS_XTEA_ALT */ + /** * \brief Initialize XTEA context * @@ -113,17 +121,7 @@ int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_XTEA_ALT */ -#include "xtea_alt.h" -#endif /* MBEDTLS_XTEA_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif +#if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine @@ -132,6 +130,8 @@ extern "C" { */ int mbedtls_xtea_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + #ifdef __cplusplus } #endif diff --git a/Externals/mbedtls/library/CMakeLists.txt b/Externals/mbedtls/library/CMakeLists.txt index ce9e939580..720c7fa17c 100644 --- a/Externals/mbedtls/library/CMakeLists.txt +++ b/Externals/mbedtls/library/CMakeLists.txt @@ -6,6 +6,7 @@ set(src_crypto aes.c aesni.c arc4.c + aria.c asn1parse.c asn1write.c base64.c @@ -13,6 +14,8 @@ set(src_crypto blowfish.c camellia.c ccm.c + chacha20.c + chachapoly.c cipher.c cipher_wrap.c cmac.c @@ -29,6 +32,7 @@ set(src_crypto error.c gcm.c havege.c + hkdf.c hmac_drbg.c md.c md2.c @@ -36,6 +40,7 @@ set(src_crypto md5.c md_wrap.c memory_buffer_alloc.c + nist_kw.c oid.c padlock.c pem.c @@ -46,8 +51,11 @@ set(src_crypto pkparse.c pkwrite.c platform.c + platform_util.c + poly1305.c ripemd160.c rsa.c + rsa_internal.c sha1.c sha256.c sha512.c @@ -90,10 +98,27 @@ if(CMAKE_COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code") endif(CMAKE_COMPILER_IS_CLANG) +if(UNSAFE_BUILD) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error") + set(CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} -Wno-error") + set(CMAKE_C_FLAGS_ASANDBG "${CMAKE_C_FLAGS_ASANDBG} -Wno-error") +endif(UNSAFE_BUILD) + if(WIN32) set(libs ${libs} ws2_32) endif(WIN32) +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(CMAKE_C_ARCHIVE_CREATE " Scr ") + SET(CMAKE_CXX_ARCHIVE_CREATE " Scr ") + SET(CMAKE_C_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") + SET(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") +endif() + +if(HAIKU) + set(libs ${libs} network) +endif(HAIKU) + if(USE_PKCS11_HELPER_LIBRARY) set(libs ${libs} pkcs11-helper) endif(USE_PKCS11_HELPER_LIBRARY) @@ -140,15 +165,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY) if(USE_SHARED_MBEDTLS_LIBRARY) add_library(mbedcrypto SHARED ${src_crypto}) - set_target_properties(mbedcrypto PROPERTIES VERSION 2.4.1 SOVERSION 0) + set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.1 SOVERSION 3) target_link_libraries(mbedcrypto ${libs}) add_library(mbedx509 SHARED ${src_x509}) - set_target_properties(mbedx509 PROPERTIES VERSION 2.4.1 SOVERSION 0) + set_target_properties(mbedx509 PROPERTIES VERSION 2.16.1 SOVERSION 0) target_link_libraries(mbedx509 ${libs} mbedcrypto) add_library(mbedtls SHARED ${src_tls}) - set_target_properties(mbedtls PROPERTIES VERSION 2.4.1 SOVERSION 10) + set_target_properties(mbedtls PROPERTIES VERSION 2.16.1 SOVERSION 12) target_link_libraries(mbedtls ${libs} mbedx509) install(TARGETS mbedtls mbedx509 mbedcrypto @@ -156,7 +181,7 @@ if(USE_SHARED_MBEDTLS_LIBRARY) PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif(USE_SHARED_MBEDTLS_LIBRARY) -#add_custom_target(lib DEPENDS mbedcrypto mbedx509 mbedtls) -#if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) -# add_dependencies(lib mbedcrypto_static mbedx509_static mbedtls_static) -#endif() +add_custom_target(lib DEPENDS mbedcrypto mbedx509 mbedtls) +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + add_dependencies(lib mbedcrypto_static mbedx509_static mbedtls_static) +endif() diff --git a/Externals/mbedtls/library/Makefile b/Externals/mbedtls/library/Makefile index 28f92315a0..430c598812 100644 --- a/Externals/mbedtls/library/Makefile +++ b/Externals/mbedtls/library/Makefile @@ -21,6 +21,10 @@ endif # if were running on Windows build for Windows ifdef WINDOWS WINDOWS_BUILD=1 +else ifeq ($(shell uname -s),Darwin) +ifeq ($(AR),ar) +APPLE_BUILD ?= 1 +endif endif # To compile as a shared library: @@ -31,37 +35,55 @@ LOCAL_CFLAGS += -fPIC -fpic endif endif -SOEXT_TLS=so.10 +SOEXT_TLS=so.12 SOEXT_X509=so.0 -SOEXT_CRYPTO=so.0 +SOEXT_CRYPTO=so.3 -DLEXT=so -# OSX shared library extension: -# DLEXT=dylib +# Set AR_DASH= (empty string) to use an ar implentation that does not accept +# the - prefix for command line options (e.g. llvm-ar) +AR_DASH ?= - -# Windows shared library extension: +ARFLAGS = $(AR_DASH)src +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) +ARFLAGS = $(AR_DASH)Src +RLFLAGS = -no_warning_for_no_symbols -c +RL ?= ranlib +endif +endif + +DLEXT ?= so ifdef WINDOWS_BUILD -DLEXT=dll +# Windows shared library extension: +DLEXT = dll +else ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) +# Mac OS X shared library extension: +DLEXT = dylib +endif endif OBJS_CRYPTO= aes.o aesni.o arc4.o \ - asn1parse.o asn1write.o base64.o \ - bignum.o blowfish.o camellia.o \ - ccm.o cipher.o cipher_wrap.o \ + aria.o asn1parse.o asn1write.o \ + base64.o bignum.o blowfish.o \ + camellia.o ccm.o chacha20.o \ + chachapoly.o cipher.o cipher_wrap.o \ cmac.o ctr_drbg.o des.o \ dhm.o ecdh.o ecdsa.o \ ecjpake.o ecp.o \ ecp_curves.o entropy.o entropy_poll.o \ error.o gcm.o havege.o \ + hkdf.o \ hmac_drbg.o md.o md2.o \ md4.o md5.o md_wrap.o \ - memory_buffer_alloc.o oid.o \ - padlock.o pem.o pk.o \ - pk_wrap.o pkcs12.o pkcs5.o \ - pkparse.o pkwrite.o platform.o \ - ripemd160.o rsa.o sha1.o \ - sha256.o sha512.o threading.o \ - timing.o version.o \ + memory_buffer_alloc.o nist_kw.o \ + oid.o padlock.o pem.o \ + pk.o pk_wrap.o pkcs12.o \ + pkcs5.o pkparse.o pkwrite.o \ + platform.o platform_util.o poly1305.o \ + ripemd160.o rsa_internal.o rsa.o \ + sha1.o sha256.o sha512.o \ + threading.o timing.o version.o \ version_features.o xtea.o OBJS_X509= certs.o pkcs11.o x509.o \ @@ -91,9 +113,13 @@ shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT) # tls libmbedtls.a: $(OBJS_TLS) echo " AR $@" - $(AR) -rc $@ $(OBJS_TLS) + $(AR) $(ARFLAGS) $@ $(OBJS_TLS) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) echo " RL $@" - $(AR) -s $@ + $(RL) $(RLFLAGS) $@ +endif +endif libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so echo " LD $@" @@ -103,9 +129,9 @@ libmbedtls.so: libmbedtls.$(SOEXT_TLS) echo " LN $@ -> $<" ln -sf $< $@ -libmbedtls.dylib: $(OBJS_TLS) +libmbedtls.dylib: $(OBJS_TLS) libmbedx509.dylib echo " LD $@" - $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + $(CC) -dynamiclib -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll echo " LD $@" @@ -114,9 +140,13 @@ libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll # x509 libmbedx509.a: $(OBJS_X509) echo " AR $@" - $(AR) -rc $@ $(OBJS_X509) + $(AR) $(ARFLAGS) $@ $(OBJS_X509) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) echo " RL $@" - $(AR) -s $@ + $(RL) $(RLFLAGS) $@ +endif +endif libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so echo " LD $@" @@ -126,9 +156,9 @@ libmbedx509.so: libmbedx509.$(SOEXT_X509) echo " LN $@ -> $<" ln -sf $< $@ -libmbedx509.dylib: $(OBJS_X509) +libmbedx509.dylib: $(OBJS_X509) libmbedcrypto.dylib echo " LD $@" - $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + $(CC) -dynamiclib -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll echo " LD $@" @@ -137,9 +167,13 @@ libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll # crypto libmbedcrypto.a: $(OBJS_CRYPTO) echo " AR $@" - $(AR) -rc $@ $(OBJS_CRYPTO) + $(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) echo " RL $@" - $(AR) -s $@ + $(RL) $(RLFLAGS) $@ +endif +endif libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO) echo " LD $@" diff --git a/Externals/mbedtls/library/aes.c b/Externals/mbedtls/library/aes.c index a186dee981..0543cd7817 100644 --- a/Externals/mbedtls/library/aes.c +++ b/Externals/mbedtls/library/aes.c @@ -36,6 +36,8 @@ #include #include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" #if defined(MBEDTLS_PADLOCK_C) #include "mbedtls/padlock.h" #endif @@ -54,10 +56,11 @@ #if !defined(MBEDTLS_AES_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) +#define AES_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) /* * 32-bit integer manipulation macros (little endian) @@ -201,6 +204,8 @@ static const unsigned char FSb[256] = static const uint32_t FT0[256] = { FT }; #undef V +#if !defined(MBEDTLS_AES_FEWER_TABLES) + #define V(a,b,c,d) 0x##b##c##d##a static const uint32_t FT1[256] = { FT }; #undef V @@ -213,6 +218,8 @@ static const uint32_t FT2[256] = { FT }; static const uint32_t FT3[256] = { FT }; #undef V +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + #undef FT /* @@ -328,6 +335,8 @@ static const unsigned char RSb[256] = static const uint32_t RT0[256] = { RT }; #undef V +#if !defined(MBEDTLS_AES_FEWER_TABLES) + #define V(a,b,c,d) 0x##b##c##d##a static const uint32_t RT1[256] = { RT }; #undef V @@ -340,6 +349,8 @@ static const uint32_t RT2[256] = { RT }; static const uint32_t RT3[256] = { RT }; #undef V +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + #undef RT /* @@ -359,18 +370,22 @@ static const uint32_t RCON[10] = */ static unsigned char FSb[256]; static uint32_t FT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) static uint32_t FT1[256]; static uint32_t FT2[256]; static uint32_t FT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ /* * Reverse S-box & tables */ static unsigned char RSb[256]; static uint32_t RT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) static uint32_t RT1[256]; static uint32_t RT2[256]; static uint32_t RT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ /* * Round constants @@ -445,9 +460,11 @@ static void aes_gen_tables( void ) ( (uint32_t) x << 16 ) ^ ( (uint32_t) z << 24 ); +#if !defined(MBEDTLS_AES_FEWER_TABLES) FT1[i] = ROTL8( FT0[i] ); FT2[i] = ROTL8( FT1[i] ); FT3[i] = ROTL8( FT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ x = RSb[i]; @@ -456,16 +473,52 @@ static void aes_gen_tables( void ) ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ ( (uint32_t) MUL( 0x0B, x ) << 24 ); +#if !defined(MBEDTLS_AES_FEWER_TABLES) RT1[i] = ROTL8( RT0[i] ); RT2[i] = ROTL8( RT1[i] ); RT3[i] = ROTL8( RT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ } } +#undef ROTL8 + #endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_AES_FEWER_TABLES) + +#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) +#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) +#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8( RT0[idx] ) +#define AES_RT2(idx) ROTL16( RT0[idx] ) +#define AES_RT3(idx) ROTL24( RT0[idx] ) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8( FT0[idx] ) +#define AES_FT2(idx) ROTL16( FT0[idx] ) +#define AES_FT3(idx) ROTL24( FT0[idx] ) + +#else /* MBEDTLS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* MBEDTLS_AES_FEWER_TABLES */ + void mbedtls_aes_init( mbedtls_aes_context *ctx ) { + AES_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); } @@ -474,9 +527,28 @@ void mbedtls_aes_free( mbedtls_aes_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); } +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + mbedtls_aes_init( &ctx->crypt ); + mbedtls_aes_init( &ctx->tweak ); +} + +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_aes_free( &ctx->crypt ); + mbedtls_aes_free( &ctx->tweak ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /* * AES key schedule (encryption) */ @@ -487,14 +559,8 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int i; uint32_t *RK; -#if !defined(MBEDTLS_AES_ROM_TABLES) - if( aes_init_done == 0 ) - { - aes_gen_tables(); - aes_init_done = 1; - - } -#endif + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); switch( keybits ) { @@ -504,6 +570,14 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); } +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) if( aes_padlock_ace == -1 ) aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); @@ -603,6 +677,9 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, uint32_t *RK; uint32_t *SK; + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + mbedtls_aes_init( &cty ); #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) @@ -641,10 +718,10 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, { for( j = 0; j < 4; j++, SK++ ) { - *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ - RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ - RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ - RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + *RK++ = AES_RT0( FSb[ ( *SK ) & 0xFF ] ) ^ + AES_RT1( FSb[ ( *SK >> 8 ) & 0xFF ] ) ^ + AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^ + AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] ); } } @@ -658,61 +735,139 @@ exit: return( ret ); } -#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ - FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ - FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y0 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ - FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ - FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; } -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ - RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ - RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y2 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ - RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ - RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); +} + +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ AES_FT0( ( Y0 ) & 0xFF ) ^ \ + AES_FT1( ( Y1 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y2 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y3 >> 24 ) & 0xFF ); \ + \ + X1 = *RK++ ^ AES_FT0( ( Y1 ) & 0xFF ) ^ \ + AES_FT1( ( Y2 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y3 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y0 >> 24 ) & 0xFF ); \ + \ + X2 = *RK++ ^ AES_FT0( ( Y2 ) & 0xFF ) ^ \ + AES_FT1( ( Y3 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y0 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y1 >> 24 ) & 0xFF ); \ + \ + X3 = *RK++ ^ AES_FT0( ( Y3 ) & 0xFF ) ^ \ + AES_FT1( ( Y0 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y1 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y2 >> 24 ) & 0xFF ); \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ AES_RT0( ( Y0 ) & 0xFF ) ^ \ + AES_RT1( ( Y3 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y1 >> 24 ) & 0xFF ); \ + \ + X1 = *RK++ ^ AES_RT0( ( Y1 ) & 0xFF ) ^ \ + AES_RT1( ( Y0 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y3 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y2 >> 24 ) & 0xFF ); \ + \ + X2 = *RK++ ^ AES_RT0( ( Y2 ) & 0xFF ) ^ \ + AES_RT1( ( Y1 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y0 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y3 >> 24 ) & 0xFF ); \ + \ + X3 = *RK++ ^ AES_RT0( ( Y3 ) & 0xFF ) ^ \ + AES_RT1( ( Y2 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y1 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y0 >> 24 ) & 0xFF ); \ } /* * AES-ECB block encryption */ #if !defined(MBEDTLS_AES_ENCRYPT_ALT) -void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) { int i; uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; @@ -760,16 +915,27 @@ void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, PUT_UINT32_LE( X1, output, 4 ); PUT_UINT32_LE( X2, output, 8 ); PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); } #endif /* !MBEDTLS_AES_ENCRYPT_ALT */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_encrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + /* * AES-ECB block decryption */ #if !defined(MBEDTLS_AES_DECRYPT_ALT) -void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) { int i; uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; @@ -817,17 +983,34 @@ void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, PUT_UINT32_LE( X1, output, 4 ); PUT_UINT32_LE( X2, output, 8 ); PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); } #endif /* !MBEDTLS_AES_DECRYPT_ALT */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_decrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + /* * AES-ECB block encryption/decryption */ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) + int mode, + const unsigned char input[16], + unsigned char output[16] ) { + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); @@ -846,11 +1029,9 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, #endif if( mode == MBEDTLS_AES_ENCRYPT ) - mbedtls_aes_encrypt( ctx, input, output ); + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); else - mbedtls_aes_decrypt( ctx, input, output ); - - return( 0 ); + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); } #if defined(MBEDTLS_CIPHER_MODE_CBC) @@ -867,6 +1048,13 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, int i; unsigned char temp[16]; + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + if( length % 16 ) return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); @@ -919,6 +1107,172 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, } #endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE( a, x, 0 ); + GET_UINT64_LE( b, x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + PUT_UINT64_LE( ra, r, 0 ); + PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( data_unit != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + /* Data units must be at least 16 bytes long. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + mbedtls_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * AES-CFB128 buffer encryption/decryption @@ -932,7 +1286,20 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, unsigned char *output ) { int c; - size_t n = *iv_off; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); if( mode == MBEDTLS_AES_DECRYPT ) { @@ -970,15 +1337,21 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, * AES-CFB8 buffer encryption/decryption */ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) { unsigned char c; unsigned char ov[17]; + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); while( length-- ) { memcpy( ov, iv, 16 ); @@ -997,7 +1370,52 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, return( 0 ); } -#endif /*MBEDTLS_CIPHER_MODE_CFB */ +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* @@ -1012,7 +1430,19 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, unsigned char *output ) { int c, i; - size_t n = *nc_off; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( nc_off != NULL ); + AES_VALIDATE_RET( nonce_counter != NULL ); + AES_VALIDATE_RET( stream_block != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *nc_off; + + if ( n > 0x0F ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); while( length-- ) { @@ -1151,6 +1581,72 @@ static const unsigned char aes_test_cfb128_ct[3][64] = }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_ofb_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * AES-CTR test vectors from: @@ -1214,25 +1710,98 @@ static const int aes_test_ctr_len[3] = { 16, 32, 36 }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, +}; + +static const unsigned char aes_test_xts_pt32[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = +{ + { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, + { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, + { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + /* * Checkup routine */ int mbedtls_aes_self_test( int verbose ) { - int ret = 0, i, j, u, v; + int ret = 0, i, j, u, mode; + unsigned int keybits; unsigned char key[32]; unsigned char buf[64]; + const unsigned char *aes_tests; #if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) unsigned char iv[16]; #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char prv[16]; #endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) size_t offset; #endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) unsigned char nonce_counter[16]; unsigned char stream_block[16]; #endif @@ -1247,45 +1816,52 @@ int mbedtls_aes_self_test( int verbose ) for( i = 0; i < 6; i++ ) { u = i >> 1; - v = i & 1; + keybits = 128 + u * 64; + mode = i & 1; if( verbose != 0 ) - mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + mbedtls_printf( " AES-ECB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); memset( buf, 0, 16 ); - if( v == MBEDTLS_AES_DECRYPT ) + if( mode == MBEDTLS_AES_DECRYPT ) { - mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_ecb_dec[u]; } else { - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_ecb_enc[u]; + } - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } - if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; + for( j = 0; j < 10000; j++ ) + { + ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf ); + if( ret != 0 ) goto exit; - } + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; } if( verbose != 0 ) @@ -1302,55 +1878,64 @@ int mbedtls_aes_self_test( int verbose ) for( i = 0; i < 6; i++ ) { u = i >> 1; - v = i & 1; + keybits = 128 + u * 64; + mode = i & 1; if( verbose != 0 ) - mbedtls_printf( " AES-CBC-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + mbedtls_printf( " AES-CBC-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); memset( iv , 0, 16 ); memset( prv, 0, 16 ); memset( buf, 0, 16 ); - if( v == MBEDTLS_AES_DECRYPT ) + if( mode == MBEDTLS_AES_DECRYPT ) { - mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_cbc_dec[u]; } else { - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_cbc_enc[u]; + } - for( j = 0; j < 10000; j++ ) + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + if( mode == MBEDTLS_AES_ENCRYPT ) { unsigned char tmp[16]; - mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - memcpy( tmp, prv, 16 ); memcpy( prv, buf, 16 ); memcpy( buf, tmp, 16 ); } - if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; + ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf ); + if( ret != 0 ) goto exit; - } + + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; } if( verbose != 0 ) @@ -1368,45 +1953,52 @@ int mbedtls_aes_self_test( int verbose ) for( i = 0; i < 6; i++ ) { u = i >> 1; - v = i & 1; + keybits = 128 + u * 64; + mode = i & 1; if( verbose != 0 ) - mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); memcpy( iv, aes_test_cfb128_iv, 16 ); - memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); + memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); offset = 0; - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } - if( v == MBEDTLS_AES_DECRYPT ) + if( mode == MBEDTLS_AES_DECRYPT ) { memcpy( buf, aes_test_cfb128_ct[u], 64 ); - mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } + aes_tests = aes_test_cfb128_pt; } else { memcpy( buf, aes_test_cfb128_pt, 64 ); - mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + aes_tests = aes_test_cfb128_ct[u]; + } - if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); + ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; - ret = 1; - goto exit; - } + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; } if( verbose != 0 ) @@ -1417,6 +2009,69 @@ int mbedtls_aes_self_test( int verbose ) mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-OFB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_ofb_iv, 16 ); + memcpy( key, aes_test_ofb_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ofb_ct[u], 64 ); + aes_tests = aes_test_ofb_pt; + } + else + { + memcpy( buf, aes_test_ofb_pt, 64 ); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * CTR mode @@ -1424,51 +2079,41 @@ int mbedtls_aes_self_test( int verbose ) for( i = 0; i < 6; i++ ) { u = i >> 1; - v = i & 1; + mode = i & 1; if( verbose != 0 ) mbedtls_printf( " AES-CTR-128 (%s): ", - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); memcpy( key, aes_test_ctr_key[u], 16 ); offset = 0; - mbedtls_aes_setkey_enc( &ctx, key, 128 ); + if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) + goto exit; - if( v == MBEDTLS_AES_DECRYPT ) + len = aes_test_ctr_len[u]; + + if( mode == MBEDTLS_AES_DECRYPT ) { - len = aes_test_ctr_len[u]; memcpy( buf, aes_test_ctr_ct[u], len ); - - mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } + aes_tests = aes_test_ctr_pt[u]; } else { - len = aes_test_ctr_len[u]; memcpy( buf, aes_test_ctr_pt[u], len ); + aes_tests = aes_test_ctr_ct[u]; + } - mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); + ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, + stream_block, buf, buf ); + if( ret != 0 ) + goto exit; - if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; } if( verbose != 0 ) @@ -1479,9 +2124,79 @@ int mbedtls_aes_self_test( int verbose ) mbedtls_printf( "\n" ); #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init( &ctx_xts ); + + for( i = 0; i < num_tests << 1; i++ ) + { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-XTS-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( key, 0, sizeof( key ) ); + memcpy( key, aes_test_xts_key[u], 32 ); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof( *aes_test_xts_ct32 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_ct32[u], len ); + aes_tests = aes_test_xts_pt32[u]; + } + else + { + ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_pt32[u], len ); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, + buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + mbedtls_aes_xts_free( &ctx_xts ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + ret = 0; exit: + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "failed\n" ); + mbedtls_aes_free( &ctx ); return( ret ); diff --git a/Externals/mbedtls/library/aesni.c b/Externals/mbedtls/library/aesni.c index 1ca3c3ef5b..062708b047 100644 --- a/Externals/mbedtls/library/aesni.c +++ b/Externals/mbedtls/library/aesni.c @@ -32,6 +32,12 @@ #if defined(MBEDTLS_AESNI_C) +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." +#endif +#endif + #include "mbedtls/aesni.h" #include diff --git a/Externals/mbedtls/library/arc4.c b/Externals/mbedtls/library/arc4.c index 05b33d3fdb..b8998ac6cd 100644 --- a/Externals/mbedtls/library/arc4.c +++ b/Externals/mbedtls/library/arc4.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_ARC4_C) #include "mbedtls/arc4.h" +#include "mbedtls/platform_util.h" #include @@ -47,11 +48,6 @@ #if !defined(MBEDTLS_ARC4_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); @@ -62,7 +58,7 @@ void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); } /* diff --git a/Externals/mbedtls/library/aria.c b/Externals/mbedtls/library/aria.c new file mode 100644 index 0000000000..aff66d667f --- /dev/null +++ b/Externals/mbedtls/library/aria.c @@ -0,0 +1,1079 @@ +/* + * ARIA implementation + * + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +/* + * This implementation is based on the following standards: + * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf + * [2] https://tools.ietf.org/html/rfc5794 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ARIA_C) + +#include "mbedtls/aria.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARIA_ALT) + +#include "mbedtls/platform_util.h" + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define ARIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) +#define ARIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE( n, b, i ) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE( n, b, i ) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +/* + * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes + * + * This is submatrix P1 in [1] Appendix B.1 + * + * Common compilers fail to translate this to minimal number of instructions, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev16 available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P1 aria_p1 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 r, x" ); + return( r ); +} +#define ARIA_P1 aria_p1 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +/* I couldn't find an Intel equivalent of rev16, so two instructions */ +#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) ) +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P1) +#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) +#endif + +/* + * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits + * + * This is submatrix P2 in [1] Appendix B.1 + * + * Common compilers will translate this to a single instruction. + */ +#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) + +/* + * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness + * + * This is submatrix P3 in [1] Appendix B.1 + * + * Some compilers fail to translate this to a single instruction, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P3 aria_p3 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev r, x" ); + return( r ); +} +#define ARIA_P3 aria_p3 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +static inline uint32_t aria_p3( uint32_t x ) +{ + __asm( "bswap %0" : "=r" (x) : "0" (x) ); + return( x ); +} +#define ARIA_P3 aria_p3 +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P3) +#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) ) +#endif + +/* + * ARIA Affine Transform + * (a, b, c, d) = state in/out + * + * If we denote the first byte of input by 0, ..., the last byte by f, + * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. + * + * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple + * rearrangements on adjacent pairs, output is: + * + * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe + * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd + * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd + * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc + * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe + * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc + * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef + * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef + * + * Note: another presentation of the A transform can be found as the first + * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. + * The implementation below uses only P1 and P2 as they are sufficient. + */ +static inline void aria_a( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d ) +{ + uint32_t ta, tb, tc; + ta = *b; // 4567 + *b = *a; // 0123 + *a = ARIA_P2( ta ); // 6745 + tb = ARIA_P2( *d ); // efcd + *d = ARIA_P1( *c ); // 98ba + *c = ARIA_P1( tb ); // fedc + ta ^= *d; // 4567+98ba + tc = ARIA_P2( *b ); // 2301 + ta = ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc + tb ^= ARIA_P2( *d ); // ba98+efcd + tc ^= ARIA_P1( *a ); // 2301+7654 + *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT + tb = ARIA_P2( tb ) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc + *a ^= ARIA_P1( tb ); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT + ta = ARIA_P2( ta ); // 0123+7654+ab89+dcfe + *d ^= ARIA_P1( ta ) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT + tc = ARIA_P2( tc ); // 0123+5476 + *c ^= ARIA_P1( tc ) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT +} + +/* + * ARIA Substitution Layer SL1 / SL2 + * (a, b, c, d) = state in/out + * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) + * + * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 + * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 + */ +static inline void aria_sl( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d, + const uint8_t sa[256], const uint8_t sb[256], + const uint8_t sc[256], const uint8_t sd[256] ) +{ + *a = ( (uint32_t) sa[ *a & 0xFF] ) ^ + (((uint32_t) sb[(*a >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*a >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *a >> 24 ]) << 24); + *b = ( (uint32_t) sa[ *b & 0xFF] ) ^ + (((uint32_t) sb[(*b >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*b >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *b >> 24 ]) << 24); + *c = ( (uint32_t) sa[ *c & 0xFF] ) ^ + (((uint32_t) sb[(*c >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*c >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *c >> 24 ]) << 24); + *d = ( (uint32_t) sa[ *d & 0xFF] ) ^ + (((uint32_t) sb[(*d >> 8) & 0xFF]) << 8) ^ + (((uint32_t) sc[(*d >> 16) & 0xFF]) << 16) ^ + (((uint32_t) sd[ *d >> 24 ]) << 24); +} + +/* + * S-Boxes + */ +static const uint8_t aria_sb1[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, + 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, + 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, + 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, + 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, + 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, + 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, + 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, + 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, + 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, + 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, + 0xB0, 0x54, 0xBB, 0x16 +}; + +static const uint8_t aria_sb2[256] = +{ + 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, + 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, + 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, + 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, + 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, + 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, + 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, + 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, + 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, + 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, + 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, + 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, + 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, + 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, + 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, + 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, + 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, + 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, + 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, + 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, + 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, + 0xAF, 0xBA, 0xB5, 0x81 +}; + +static const uint8_t aria_is1[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, + 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, + 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, + 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, + 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, + 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, + 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, + 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, + 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, + 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0C, 0x7D +}; + +static const uint8_t aria_is2[256] = +{ + 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, + 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, + 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, + 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, + 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, + 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, + 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, + 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, + 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, + 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, + 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, + 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, + 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, + 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, + 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, + 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, + 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, + 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, + 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, + 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, + 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, + 0x03, 0xA2, 0xAC, 0x60 +}; + +/* + * Helper for key schedule: r = FO( p, k ) ^ x + */ +static void aria_fo_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Helper for key schedule: r = FE( p, k ) ^ x + */ +static void aria_fe_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. + * + * We chose to store bytes into 32-bit words in little-endian format (see + * GET/PUT_UINT32_LE) so we need to reverse bytes here. + */ +static void aria_rot128( uint32_t r[4], const uint32_t a[4], + const uint32_t b[4], uint8_t n ) +{ + uint8_t i, j; + uint32_t t, u; + + const uint8_t n1 = n % 32; // bit offset + const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset + + j = ( n / 32 ) % 4; // initial word offset + t = ARIA_P3( b[j] ); // big endian + for( i = 0; i < 4; i++ ) + { + j = ( j + 1 ) % 4; // get next word, big endian + u = ARIA_P3( b[j] ); + t <<= n1; // rotate + t |= u >> n2; + t = ARIA_P3( t ); // back to little endian + r[i] = a[i] ^ t; // store + t = u; // move to next word + } +} + +/* + * Set encryption key + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + /* round constant masks */ + const uint32_t rc[3][4] = + { + { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, + { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, + { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } + }; + + int i; + uint32_t w[4][4], *w2; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + if( keybits != 128 && keybits != 192 && keybits != 256 ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + /* Copy key to W0 (and potential remainder to W1) */ + GET_UINT32_LE( w[0][0], key, 0 ); + GET_UINT32_LE( w[0][1], key, 4 ); + GET_UINT32_LE( w[0][2], key, 8 ); + GET_UINT32_LE( w[0][3], key, 12 ); + + memset( w[1], 0, 16 ); + if( keybits >= 192 ) + { + GET_UINT32_LE( w[1][0], key, 16 ); // 192 bit key + GET_UINT32_LE( w[1][1], key, 20 ); + } + if( keybits == 256 ) + { + GET_UINT32_LE( w[1][2], key, 24 ); // 256 bit key + GET_UINT32_LE( w[1][3], key, 28 ); + } + + i = ( keybits - 128 ) >> 6; // index: 0, 1, 2 + ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 + + aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR + i = i < 2 ? i + 1 : 0; + aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0 + i = i < 2 ? i + 1 : 0; + aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1 + + for( i = 0; i < 4; i++ ) // create round keys + { + w2 = w[(i + 1) & 3]; + aria_rot128( ctx->rk[i ], w[i], w2, 128 - 19 ); + aria_rot128( ctx->rk[i + 4], w[i], w2, 128 - 31 ); + aria_rot128( ctx->rk[i + 8], w[i], w2, 61 ); + aria_rot128( ctx->rk[i + 12], w[i], w2, 31 ); + } + aria_rot128( ctx->rk[16], w[0], w[1], 19 ); + + /* w holds enough info to reconstruct the round keys */ + mbedtls_platform_zeroize( w, sizeof( w ) ); + + return( 0 ); +} + +/* + * Set decryption key + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + int i, j, k, ret; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aria_setkey_enc( ctx, key, keybits ); + if( ret != 0 ) + return( ret ); + + /* flip the order of round keys */ + for( i = 0, j = ctx->nr; i < j; i++, j-- ) + { + for( k = 0; k < 4; k++ ) + { + uint32_t t = ctx->rk[i][k]; + ctx->rk[i][k] = ctx->rk[j][k]; + ctx->rk[j][k] = t; + } + } + + /* apply affine transform to middle keys */ + for( i = 1; i < ctx->nr; i++ ) + { + aria_a( &ctx->rk[i][0], &ctx->rk[i][1], + &ctx->rk[i][2], &ctx->rk[i][3] ); + } + + return( 0 ); +} + +/* + * Encrypt a block + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ) +{ + int i; + + uint32_t a, b, c, d; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( input != NULL ); + ARIA_VALIDATE_RET( output != NULL ); + + GET_UINT32_LE( a, input, 0 ); + GET_UINT32_LE( b, input, 4 ); + GET_UINT32_LE( c, input, 8 ); + GET_UINT32_LE( d, input, 12 ); + + i = 0; + while( 1 ) + { + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + if( i >= ctx->nr ) + break; + aria_a( &a, &b, &c, &d ); + } + + /* final key mixing */ + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + + PUT_UINT32_LE( a, output, 0 ); + PUT_UINT32_LE( b, output, 4 ); + PUT_UINT32_LE( c, output, 8 ); + PUT_UINT32_LE( d, output, 12 ); + + return( 0 ); +} + +/* Initialize context */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ) +{ + ARIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_aria_context ) ); +} + +/* Clear context */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * ARIA-CBC buffer encryption/decryption + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + + if( length % MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE ); + mbedtls_aria_crypt_ecb( ctx, input, output ); + + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aria_crypt_ecb( ctx, output, output ); + memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * ARIA-CFB128 buffer encryption/decryption + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + ARIA_VALIDATE_RET( iv_off != NULL ); + + n = *iv_off; + + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + c = *input++; + *output++ = c ^ iv[n]; + iv[n] = c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * ARIA-CTR buffer encryption/decryption + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( nonce_counter != NULL ); + ARIA_VALIDATE_RET( stream_block != NULL ); + ARIA_VALIDATE_RET( nc_off != NULL ); + + n = *nc_off; + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aria_crypt_ecb( ctx, nonce_counter, + stream_block ); + + for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_ARIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Basic ARIA ECB test vectors from RFC 5794 + */ +static const uint8_t aria_test1_ecb_key[32] = // test key +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit +}; + +static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes +}; + +static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext +{ + { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit + 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, + { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit + 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, + { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit + 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } +}; + +/* + * Mode tests from "Test Vectors for ARIA" Version 1.0 + * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf + */ +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) +static const uint8_t aria_test2_key[32] = +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit +}; + +static const uint8_t aria_test2_pt[48] = +{ + 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all + 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, + 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, + 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, + 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, + 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, +}; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) +static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = +{ + 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB + 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV +}; +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext +{ + { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key + 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, + 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, + 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, + 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, + 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, + { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key + 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, + 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, + 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, + 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, + 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, + { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key + 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, + 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, + 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, + 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, + 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext +{ + { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key + 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, + 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, + 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, + 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, + 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, + { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key + 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, + 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, + 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, + 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, + 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, + { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key + 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, + 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, + 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, + 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, + 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext +{ + { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key + 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, + 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, + 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, + 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, + 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, + { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key + 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, + 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, + 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, + 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, + 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, + { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key + 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, + 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, + 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, + 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, + 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#define ARIA_SELF_TEST_IF_FAIL \ + { \ + if( verbose ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } else { \ + if( verbose ) \ + mbedtls_printf( "passed\n" ); \ + } + +/* + * Checkup routine + */ +int mbedtls_aria_self_test( int verbose ) +{ + int i; + uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; + mbedtls_aria_context ctx; + +#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) + size_t j; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ + defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) + uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; +#endif + + /* + * Test set 1 + */ + for( i = 0; i < 3; i++ ) + { + /* test ECB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk ); + if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* test ECB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk ); + if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + + /* + * Test set 2 + */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + for( i = 0; i < 3; i++ ) + { + /* Test CBC encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CBC decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, + aria_test2_cbc_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + for( i = 0; i < 3; i++ ) + { + /* Test CFB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CFB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, + iv, aria_test2_cfb_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + for( i = 0; i < 3; i++ ) + { + /* Test CTR encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CTR decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_ctr_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARIA_C */ diff --git a/Externals/mbedtls/library/asn1parse.c b/Externals/mbedtls/library/asn1parse.c index 4dd65c03c0..171c340b8c 100644 --- a/Externals/mbedtls/library/asn1parse.c +++ b/Externals/mbedtls/library/asn1parse.c @@ -28,6 +28,7 @@ #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" +#include "mbedtls/platform_util.h" #include @@ -43,11 +44,6 @@ #define mbedtls_free free #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * ASN.1 DER decoding routines */ @@ -313,7 +309,7 @@ int mbedtls_asn1_get_alg( unsigned char **p, if( *p == end ) { - mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) ); + mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); return( 0 ); } @@ -358,7 +354,7 @@ void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) mbedtls_free( cur->oid.p ); mbedtls_free( cur->val.p ); - mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); + mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); } void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) diff --git a/Externals/mbedtls/library/asn1write.c b/Externals/mbedtls/library/asn1write.c index 69b61b205f..c0b4622d58 100644 --- a/Externals/mbedtls/library/asn1write.c +++ b/Externals/mbedtls/library/asn1write.c @@ -83,7 +83,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len return( 4 ); } +#if SIZE_MAX > 0xFFFFFFFF if( len <= 0xFFFFFFFF ) +#endif { if( *p - start < 5 ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); @@ -96,7 +98,9 @@ int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len return( 5 ); } +#if SIZE_MAX > 0xFFFFFFFF return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif } int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) @@ -232,10 +236,6 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) int ret; size_t len = 0; - // TODO negative values and values larger than 128 - // DER format assumes 2s complement for numbers, so the leftmost bit - // should be 0 for positive numbers and 1 for negative numbers. - // if( *p - start < 1 ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); @@ -257,56 +257,65 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) return( (int) len ); } -int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ) +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, + const char *text, size_t text_len ) { int ret; size_t len = 0; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) text, text_len ) ); + (const unsigned char *) text, text_len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); return( (int) len ); } +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); +} + int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, const char *text, size_t text_len ) { - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) text, text_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) ); - - return( (int) len ); + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); } int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, const unsigned char *buf, size_t bits ) { int ret; - size_t len = 0, size; + size_t len = 0; + size_t unused_bits, byte_len; - size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; - // Calculate byte length - // - if( *p < start || (size_t)( *p - start ) < size + 1 ) + if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - len = size + 1; - (*p) -= size; - memcpy( *p, buf, size ); + len = byte_len + 1; - // Write unused bits - // - *--(*p) = (unsigned char) (size * 8 - bits); + /* Write the bitstring. Ensure the unused bits are zeroed */ + if( byte_len > 0 ) + { + byte_len--; + *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); + ( *p ) -= byte_len; + memcpy( *p, buf, byte_len ); + } + + /* Write unused bits */ + *--( *p ) = (unsigned char)unused_bits; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); @@ -328,14 +337,36 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, return( (int) len ); } -mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, + +/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), + * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ +static mbedtls_asn1_named_data *asn1_find_named_data( + mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( + mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len ) { mbedtls_asn1_named_data *cur; - if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) { // Add new entry if not present yet based on OID // diff --git a/Externals/mbedtls/library/base64.c b/Externals/mbedtls/library/base64.c index 5cb12cba75..f06b57b31f 100644 --- a/Externals/mbedtls/library/base64.c +++ b/Externals/mbedtls/library/base64.c @@ -192,7 +192,11 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, return( 0 ); } - n = ( ( n * 6 ) + 7 ) >> 3; + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); n -= j; if( dst == NULL || dlen < n ) diff --git a/Externals/mbedtls/library/bignum.c b/Externals/mbedtls/library/bignum.c index 4c99e04d6f..87015af0c8 100644 --- a/Externals/mbedtls/library/bignum.c +++ b/Externals/mbedtls/library/bignum.c @@ -45,6 +45,7 @@ #include "mbedtls/bignum.h" #include "mbedtls/bn_mul.h" +#include "mbedtls/platform_util.h" #include @@ -58,10 +59,10 @@ #define mbedtls_free free #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { - volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; -} +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ #define biL (ciL << 3) /* bits in limb */ @@ -76,13 +77,18 @@ static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { #define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) #define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) +{ + mbedtls_platform_zeroize( v, ciL * n ); +} + /* * Initialize one MPI */ void mbedtls_mpi_init( mbedtls_mpi *X ) { - if( X == NULL ) - return; + MPI_VALIDATE( X != NULL ); X->s = 1; X->n = 0; @@ -114,6 +120,7 @@ void mbedtls_mpi_free( mbedtls_mpi *X ) int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) { mbedtls_mpi_uint *p; + MPI_VALIDATE_RET( X != NULL ); if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); @@ -145,6 +152,10 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) { mbedtls_mpi_uint *p; size_t i; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); /* Actually resize up in this case */ if( X->n <= nblimbs ) @@ -179,8 +190,10 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) */ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) { - int ret; + int ret = 0; size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); if( X == Y ) return( 0 ); @@ -198,9 +211,15 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) X->s = Y->s; - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } - memset( X->p, 0, X->n * ciL ); memcpy( X->p, Y->p, i * ciL ); cleanup: @@ -214,6 +233,8 @@ cleanup: void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) { mbedtls_mpi T; + MPI_VALIDATE( X != NULL ); + MPI_VALIDATE( Y != NULL ); memcpy( &T, X, sizeof( mbedtls_mpi ) ); memcpy( X, Y, sizeof( mbedtls_mpi ) ); @@ -229,6 +250,8 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned { int ret = 0; size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); /* make sure assign is 0 or 1 in a time-constant manner */ assign = (assign | (unsigned char)-assign) >> 7; @@ -258,6 +281,8 @@ int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char sw int ret, s; size_t i; mbedtls_mpi_uint tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); if( X == Y ) return( 0 ); @@ -290,6 +315,7 @@ cleanup: int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) { int ret; + MPI_VALIDATE_RET( X != NULL ); MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); memset( X->p, 0, X->n * ciL ); @@ -307,12 +333,18 @@ cleanup: */ int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) { + MPI_VALIDATE_RET( X != NULL ); + if( X->n * biL <= pos ) return( 0 ); return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); } +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + /* * Set a bit to a specific value of 0 or 1 */ @@ -321,6 +353,7 @@ int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) int ret = 0; size_t off = pos / biL; size_t idx = pos % biL; + MPI_VALIDATE_RET( X != NULL ); if( val != 0 && val != 1 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -347,6 +380,7 @@ cleanup: size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) { size_t i, j, count = 0; + MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); for( i = 0; i < X->n; i++ ) for( j = 0; j < biL; j++, count++ ) @@ -427,6 +461,8 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) size_t i, j, slen, n; mbedtls_mpi_uint d; mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( s != NULL ); if( radix < 2 || radix > 16 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -491,26 +527,38 @@ cleanup: } /* - * Helper to write the digits high-order first + * Helper to write the digits high-order first. */ -static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) +static int mpi_write_hlp( mbedtls_mpi *X, int radix, + char **p, const size_t buflen ) { int ret; mbedtls_mpi_uint r; + size_t length = 0; + char *p_end = *p + buflen; - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + do + { + if( length >= buflen ) + { + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + /* + * Write the residue in the current position, as an ASCII character. + */ + if( r < 0xA ) + *(--p_end) = (char)( '0' + r ); + else + *(--p_end) = (char)( 'A' + ( r - 0xA ) ); - if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) - MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); + length++; + } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); - if( r < 10 ) - *(*p)++ = (char)( r + 0x30 ); - else - *(*p)++ = (char)( r + 0x37 ); + memmove( *p, p_end, length ); + *p += length; cleanup: @@ -527,6 +575,9 @@ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, size_t n; char *p; mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( olen != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); if( radix < 2 || radix > 16 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -534,7 +585,12 @@ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, n = mbedtls_mpi_bitlen( X ); if( radix >= 4 ) n >>= 1; if( radix >= 16 ) n >>= 1; - n += 3; + /* + * Round up the buffer length to an even value to ensure that there is + * enough room for hexadecimal values that can be represented in an odd + * number of digits. + */ + n += 3 + ( ( n + 1 ) & 1 ); if( buflen < n ) { @@ -575,7 +631,7 @@ int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, if( T.s == -1 ) T.s = 1; - MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); } *p++ = '\0'; @@ -603,6 +659,12 @@ int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) */ char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( fin != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + memset( s, 0, sizeof( s ) ); if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); @@ -611,11 +673,11 @@ int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) if( slen == sizeof( s ) - 2 ) return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } - if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } p = s + slen; - while( --p >= s ) + while( p-- > s ) if( mpi_get_digit( &d, radix, *p ) != 0 ) break; @@ -634,6 +696,10 @@ int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE * newline characters and '\0' */ char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); memset( s, 0, sizeof( s ) ); @@ -661,23 +727,123 @@ cleanup: } #endif /* MBEDTLS_FS_IO */ + +/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. */ + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) +{ + uint8_t i; + mbedtls_mpi_uint tmp = 0; + /* This works regardless of the endianness. */ + for( i = 0; i < ciL; i++, x >>= 8 ) + tmp |= ( x & 0xFF ) << ( ( ciL - 1 - i ) << 3 ); + return( tmp ); +} + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) +{ +#if defined(__BYTE_ORDER__) + +/* Nothing to do on bigendian systems. */ +#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + return( x ); +#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ + +#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + +/* For GCC and Clang, have builtins for byte swapping. */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4,3) +#define have_bswap +#endif +#endif + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap32) && \ + __has_builtin(__builtin_bswap64) +#define have_bswap +#endif +#endif + +#if defined(have_bswap) + /* The compiler is hopefully able to statically evaluate this! */ + switch( sizeof(mbedtls_mpi_uint) ) + { + case 4: + return( __builtin_bswap32(x) ); + case 8: + return( __builtin_bswap64(x) ); + } +#endif +#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ +#endif /* __BYTE_ORDER__ */ + + /* Fall back to C-based reordering if we don't know the byte order + * or we couldn't use a compiler-specific builtin. */ + return( mpi_uint_bigendian_to_host_c( x ) ); +} + +static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) +{ + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if( limbs == 0 ) + return; + + /* + * Traverse limbs and + * - adapt byte-order in each limb + * - swap the limbs themselves. + * For that, simultaneously traverse the limbs from left to right + * and from right to left, as long as the left index is not bigger + * than the right index (it's not a problem if limbs is odd and the + * indices coincide in the last iteration). + */ + for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); + cur_limb_left <= cur_limb_right; + cur_limb_left++, cur_limb_right-- ) + { + mbedtls_mpi_uint tmp; + /* Note that if cur_limb_left == cur_limb_right, + * this code effectively swaps the bytes only once. */ + tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); + *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); + *cur_limb_right = tmp; + } +} + /* * Import X from unsigned binary data, big endian */ int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) { int ret; - size_t i, j, n; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + size_t const overhead = ( limbs * ciL ) - buflen; + unsigned char *Xp; - for( n = 0; n < buflen; n++ ) - if( buf[n] != 0 ) - break; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - for( i = buflen, j = 0; i > n; i--, j++ ) - X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); + /* Avoid calling `memcpy` with NULL source argument, + * even if buflen is 0. */ + if( buf != NULL ) + { + Xp = (unsigned char*) X->p; + memcpy( Xp + overhead, buf, buflen ); + + mpi_bigendian_to_host( X->p, limbs ); + } cleanup: @@ -687,19 +853,45 @@ cleanup: /* * Export X into unsigned binary data, big endian */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) { - size_t i, j, n; + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + size_t i; - n = mbedtls_mpi_size( X ); + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); - if( buflen < n ) - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + stored_bytes = X->n * ciL; - memset( buf, 0, buflen ); + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } - for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) - buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); return( 0 ); } @@ -712,6 +904,7 @@ int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) int ret; size_t i, v0, t1; mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); v0 = count / (biL ); t1 = count & (biL - 1); @@ -761,6 +954,7 @@ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) { size_t i, v0, v1; mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); v0 = count / biL; v1 = count & (biL - 1); @@ -803,6 +997,8 @@ int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) { size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); for( i = X->n; i > 0; i-- ) if( X->p[i - 1] != 0 ) @@ -833,6 +1029,8 @@ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) { size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); for( i = X->n; i > 0; i-- ) if( X->p[i - 1] != 0 ) @@ -867,6 +1065,7 @@ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) { mbedtls_mpi Y; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); *p = ( z < 0 ) ? -z : z; Y.s = ( z < 0 ) ? -1 : 1; @@ -884,6 +1083,9 @@ int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi int ret; size_t i, j; mbedtls_mpi_uint *o, *p, c, tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); if( X == B ) { @@ -949,7 +1151,7 @@ static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) while( c != 0 ) { z = ( *d < c ); *d -= c; - c = z; i++; d++; + c = z; d++; } } @@ -961,6 +1163,9 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi mbedtls_mpi TB; int ret; size_t n; + 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 ); @@ -1001,8 +1206,12 @@ cleanup: */ int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) { - int ret, s = A->s; + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + s = A->s; if( A->s * B->s < 0 ) { if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) @@ -1032,8 +1241,12 @@ cleanup: */ int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) { - int ret, s = A->s; + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + s = A->s; if( A->s * B->s > 0 ) { if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) @@ -1065,6 +1278,8 @@ int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint { mbedtls_mpi _B; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; @@ -1081,6 +1296,8 @@ int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint { mbedtls_mpi _B; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; @@ -1170,6 +1387,9 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi int ret; size_t i, j; mbedtls_mpi TA, TB; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); @@ -1187,8 +1407,8 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - for( i++; j > 0; j-- ) - mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); X->s = A->s * B->s; @@ -1206,6 +1426,8 @@ int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint { mbedtls_mpi _B; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); _B.s = 1; _B.n = 1; @@ -1314,11 +1536,14 @@ static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, /* * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ) { int ret; size_t i, n, t, k; mbedtls_mpi X, Y, Z, T1, T2; + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); @@ -1429,10 +1654,13 @@ cleanup: /* * Division by int: A = Q * b + R */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, + const mbedtls_mpi *A, + mbedtls_mpi_sint b ) { mbedtls_mpi _B; mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( A != NULL ); p[0] = ( b < 0 ) ? -b : b; _B.s = ( b < 0 ) ? -1 : 1; @@ -1448,6 +1676,9 @@ int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, m int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) { int ret; + MPI_VALIDATE_RET( R != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); @@ -1472,6 +1703,8 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_ { size_t i; mbedtls_mpi_uint x, y, z; + MPI_VALIDATE_RET( r != NULL ); + MPI_VALIDATE_RET( A != NULL ); if( b == 0 ) return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); @@ -1585,7 +1818,8 @@ static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi /* * Montgomery reduction: A = A * R^-1 mod N */ -static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +static int 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; @@ -1599,7 +1833,9 @@ static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint m /* * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ) { int ret; size_t wbits, wsize, one = 1; @@ -1609,7 +1845,12 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; int neg; - if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) @@ -1785,7 +2026,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi */ MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); - if( neg ) + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) { X->s = -1; MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); @@ -1813,6 +2054,10 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B size_t lz, lzt; mbedtls_mpi TG, TA, TB; + MPI_VALIDATE_RET( G != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); @@ -1868,13 +2113,26 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, void *p_rng ) { int ret; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + size_t const limbs = CHARS_TO_LIMBS( size ); + size_t const overhead = ( limbs * ciL ) - size; + unsigned char *Xp; - if( size > MBEDTLS_MPI_MAX_SIZE ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); - MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + Xp = (unsigned char*) X->p; + f_rng( p_rng, Xp + overhead, size ); + + mpi_bigendian_to_host( X->p, limbs ); cleanup: return( ret ); @@ -1887,8 +2145,11 @@ int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi { int ret; mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( N != NULL ); - if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 ) + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); @@ -2038,15 +2299,19 @@ cleanup: /* * Miller-Rabin pseudo-primality test (HAC 4.24) */ -static int mpi_miller_rabin( const mbedtls_mpi *X, +static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, count; - size_t i, j, k, n, s; + size_t i, j, k, s; mbedtls_mpi W, R, T, A, RR; - mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); + mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); mbedtls_mpi_init( &RR ); /* @@ -2059,27 +2324,12 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); i = mbedtls_mpi_bitlen( X ); - /* - * HAC, table 4.4 - */ - n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : - ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : - ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); - for( i = 0; i < n; i++ ) + for( i = 0; i < rounds; i++ ) { /* * pick a random A, 1 < A < |X| - 1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) - { - j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); - } - A.p[0] |= 3; - count = 0; do { MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); @@ -2087,7 +2337,7 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, j = mbedtls_mpi_bitlen( &A ); k = mbedtls_mpi_bitlen( &W ); if (j > k) { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; } if (count++ > 30) { @@ -2133,7 +2383,8 @@ static int mpi_miller_rabin( const mbedtls_mpi *X, } cleanup: - mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); mbedtls_mpi_free( &RR ); return( ret ); @@ -2142,12 +2393,14 @@ cleanup: /* * Pseudo-primality test: small factors, then Miller-Rabin */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; mbedtls_mpi XX; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); XX.s = 1; XX.n = X->n; @@ -2168,21 +2421,56 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X, return( ret ); } - return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); + return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Pseudo-primality test, error probability 2^-80 + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* + * In the past our key generation aimed for an error rate of at most + * 2^-80. Since this function is deprecated, aim for the same certainty + * here as well. + */ + return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) ); +} +#endif + /* * Prime number generation + * + * To generate an RSA key in a way recommended by FIPS 186-4, both primes must + * be either 1024 bits or 1536 bits long, and flags must contain + * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret; +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; size_t k, n; + int rounds; mbedtls_mpi_uint r; mbedtls_mpi Y; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); @@ -2190,69 +2478,89 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, n = BITS_TO_LIMBS( nbits ); - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); - - k = mbedtls_mpi_bitlen( X ); - if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); - - mbedtls_mpi_set_bit( X, nbits-1, 1 ); - - X->p[0] |= 1; - - if( dh_flag == 0 ) + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) { - while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) - { - if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); - } + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); } else { /* - * An necessary condition for Y and X = 2Y + 1 to be prime - * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). - * Make sure it is satisfied, while keeping X = 3 mod 4 + * 2^-100 error probability, number of rounds computed based on HAC, + * fact 4.48 */ + rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : + ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : + ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : + ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); + } - X->p[0] |= 2; + while( 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); - if( r == 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); - else if( r == 1 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; - /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); - - while( 1 ) + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) { - /* - * First, check small factors for X and Y - * before doing Miller-Rabin on any of them - */ - if( ( ret = mpi_check_small_factors( X ) ) == 0 && - ( ret = mpi_check_small_factors( &Y ) ) == 0 && - ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && - ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) - { - break; - } + ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) goto cleanup; - + } + else + { /* - * Next candidates. We want to preserve Y = (X-1) / 2 and - * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) - * so up Y by 6 and X by 12. + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) + == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } } } diff --git a/Externals/mbedtls/library/blowfish.c b/Externals/mbedtls/library/blowfish.c index 9003f0dfeb..cbf9238246 100644 --- a/Externals/mbedtls/library/blowfish.c +++ b/Externals/mbedtls/library/blowfish.c @@ -34,15 +34,17 @@ #if defined(MBEDTLS_BLOWFISH_C) #include "mbedtls/blowfish.h" +#include "mbedtls/platform_util.h" #include #if !defined(MBEDTLS_BLOWFISH_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} +/* Parameter validation macros */ +#define BLOWFISH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ) +#define BLOWFISH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) /* * 32-bit integer manipulation macros (big endian) @@ -157,6 +159,7 @@ static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) { + BLOWFISH_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); } @@ -165,22 +168,26 @@ void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); } /* * Blowfish key schedule */ -int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, - unsigned int keybits ) +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, + const unsigned char *key, + unsigned int keybits ) { unsigned int i, j, k; uint32_t data, datal, datar; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( key != NULL ); - if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || - ( keybits % 8 ) ) + if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || + keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || + keybits % 8 != 0 ) { - return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH ); + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); } keybits >>= 3; @@ -235,6 +242,11 @@ int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) { uint32_t X0, X1; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( input != NULL ); + BLOWFISH_VALIDATE_RET( output != NULL ); GET_UINT32_BE( X0, input, 0 ); GET_UINT32_BE( X1, input, 4 ); @@ -267,6 +279,12 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, { int i; unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); @@ -321,7 +339,19 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, unsigned char *output ) { int c; - size_t n = *iv_off; + size_t n; + + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( iv_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); if( mode == MBEDTLS_BLOWFISH_DECRYPT ) { @@ -369,7 +399,17 @@ int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, unsigned char *output ) { int c, i; - size_t n = *nc_off; + size_t n; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( nonce_counter != NULL ); + BLOWFISH_VALIDATE_RET( stream_block != NULL ); + BLOWFISH_VALIDATE_RET( nc_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); while( length-- ) { diff --git a/Externals/mbedtls/library/camellia.c b/Externals/mbedtls/library/camellia.c index ac6f96a83a..22262b89a8 100644 --- a/Externals/mbedtls/library/camellia.c +++ b/Externals/mbedtls/library/camellia.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" +#include "mbedtls/platform_util.h" #include @@ -48,10 +49,11 @@ #if !defined(MBEDTLS_CAMELLIA_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} +/* Parameter validation macros */ +#define CAMELLIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ) +#define CAMELLIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) /* * 32-bit integer manipulation macros (big endian) @@ -325,6 +327,7 @@ static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) { + CAMELLIA_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); } @@ -333,14 +336,15 @@ void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); } /* * Camellia key schedule (encryption) */ -int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ) +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) { int idx; size_t i; @@ -350,6 +354,9 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c uint32_t KC[16]; uint32_t TK[20]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + RK = ctx->rk; memset( t, 0, 64 ); @@ -360,7 +367,7 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c case 128: ctx->nr = 3; idx = 0; break; case 192: case 256: ctx->nr = 4; idx = 1; break; - default : return( MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH ); + default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); } for( i = 0; i < keybits / 8; ++i ) @@ -444,14 +451,17 @@ int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned c /* * Camellia key schedule (decryption) */ -int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ) +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) { int idx, ret; size_t i; mbedtls_camellia_context cty; uint32_t *RK; uint32_t *SK; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); mbedtls_camellia_init( &cty ); @@ -499,6 +509,11 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, { int NR; uint32_t *RK, X[4]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( input != NULL ); + CAMELLIA_VALIDATE_RET( output != NULL ); ( (void) mode ); @@ -556,14 +571,20 @@ int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, * Camellia-CBC buffer encryption/decryption */ int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) { int i; unsigned char temp[16]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); if( length % 16 ) return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); @@ -618,7 +639,18 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, unsigned char *output ) { int c; - size_t n = *iv_off; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( iv_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); if( mode == MBEDTLS_CAMELLIA_DECRYPT ) { @@ -666,7 +698,17 @@ int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, unsigned char *output ) { int c, i; - size_t n = *nc_off; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( nonce_counter != NULL ); + CAMELLIA_VALIDATE_RET( stream_block != NULL ); + CAMELLIA_VALIDATE_RET( nc_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); while( length-- ) { diff --git a/Externals/mbedtls/library/ccm.c b/Externals/mbedtls/library/ccm.c index 13a8fd1a24..01e58b0436 100644 --- a/Externals/mbedtls/library/ccm.c +++ b/Externals/mbedtls/library/ccm.c @@ -37,6 +37,7 @@ #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" +#include "mbedtls/platform_util.h" #include @@ -49,10 +50,12 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} +#if !defined(MBEDTLS_CCM_ALT) + +#define CCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT ) +#define CCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) #define CCM_ENCRYPT 0 #define CCM_DECRYPT 1 @@ -62,6 +65,7 @@ static void mbedtls_zeroize( void *v, size_t n ) { */ void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) { + CCM_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); } @@ -73,6 +77,9 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, int ret; const mbedtls_cipher_info_t *cipher_info; + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( key != NULL ); + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); if( cipher_info == NULL ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); @@ -99,8 +106,10 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, */ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) { + if( ctx == NULL ) + return; mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); } /* @@ -154,8 +163,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, * Check length requirements: SP800-38C A.1 * Additional requirement: a < 2^16 - 2^8 to simplify the code. * 'length' checked later (when writing it to the first block) + * + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). */ - if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) + if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); /* Also implies q is within bounds */ @@ -304,20 +315,45 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, /* * Authenticated encryption */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len ) { - return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, - add, add_len, input, output, tag, tag_len ) ); + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); } /* * Authenticated decryption */ -int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, @@ -328,6 +364,13 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, unsigned char i; int diff; + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, check_tag, tag_len ) ) != 0 ) @@ -341,13 +384,33 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, if( diff != 0 ) { - mbedtls_zeroize( output, length ); + mbedtls_platform_zeroize( output, length ); return( MBEDTLS_ERR_CCM_AUTH_FAILED ); } return( 0 ); } +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} +#endif /* !MBEDTLS_CCM_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /* @@ -355,7 +418,8 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, */ #define NB_TESTS 3 - +#define CCM_SELFTEST_PT_MAX_LEN 24 +#define CCM_SELFTEST_CT_MAX_LEN 32 /* * The data is the same for all tests, only the used length changes */ @@ -375,7 +439,7 @@ static const unsigned char ad[] = { 0x10, 0x11, 0x12, 0x13 }; -static const unsigned char msg[] = { +static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, @@ -386,7 +450,7 @@ static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; -static const unsigned char res[NB_TESTS][32] = { +static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, @@ -400,7 +464,13 @@ static const unsigned char res[NB_TESTS][32] = { int mbedtls_ccm_self_test( int verbose ) { mbedtls_ccm_context ctx; - unsigned char out[32]; + /* + * Some hardware accelerators require the input and output buffers + * would be in RAM, because the flash is not accessible. + * Use buffers on the stack to hold the test vectors data. + */ + unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; + unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; size_t i; int ret; @@ -419,27 +489,32 @@ int mbedtls_ccm_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN ); + memcpy( plaintext, msg, msg_len[i] ); + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], - iv, iv_len[i], ad, add_len[i], - msg, out, - out + msg_len[i], tag_len[i] ); + iv, iv_len[i], ad, add_len[i], + plaintext, ciphertext, + ciphertext + msg_len[i], tag_len[i] ); if( ret != 0 || - memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 ) + memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); return( 1 ); } + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], - iv, iv_len[i], ad, add_len[i], - res[i], out, - res[i] + msg_len[i], tag_len[i] ); + iv, iv_len[i], ad, add_len[i], + ciphertext, plaintext, + ciphertext + msg_len[i], tag_len[i] ); if( ret != 0 || - memcmp( out, msg, msg_len[i] ) != 0 ) + memcmp( plaintext, msg, msg_len[i] ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); diff --git a/Externals/mbedtls/library/certs.c b/Externals/mbedtls/library/certs.c index ffe6bc981c..ff0f11e923 100644 --- a/Externals/mbedtls/library/certs.c +++ b/Externals/mbedtls/library/certs.c @@ -47,6 +47,7 @@ "uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ "-----END CERTIFICATE-----\r\n" const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; +const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); const char mbedtls_test_ca_key_ec[] = "-----BEGIN EC PRIVATE KEY-----\r\n" @@ -58,8 +59,10 @@ const char mbedtls_test_ca_key_ec[] = "UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" "a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" "-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_ca_key_ec_len = sizeof( mbedtls_test_ca_key_ec ); const char mbedtls_test_ca_pwd_ec[] = "PolarSSLTest"; +const size_t mbedtls_test_ca_pwd_ec_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; const char mbedtls_test_srv_crt_ec[] = "-----BEGIN CERTIFICATE-----\r\n" @@ -76,6 +79,7 @@ const char mbedtls_test_srv_crt_ec[] = "C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" "fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" "-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); const char mbedtls_test_srv_key_ec[] = "-----BEGIN EC PRIVATE KEY-----\r\n" @@ -83,6 +87,7 @@ const char mbedtls_test_srv_key_ec[] = "AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" "6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" "-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); const char mbedtls_test_cli_crt_ec[] = "-----BEGIN CERTIFICATE-----\r\n" @@ -99,6 +104,7 @@ const char mbedtls_test_cli_crt_ec[] = "lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" "LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" "-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); const char mbedtls_test_cli_key_ec[] = "-----BEGIN EC PRIVATE KEY-----\r\n" @@ -106,20 +112,45 @@ const char mbedtls_test_cli_key_ec[] = "AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" "wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" "-----END EC PRIVATE KEY-----\r\n"; - -const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); -const size_t mbedtls_test_ca_key_ec_len = sizeof( mbedtls_test_ca_key_ec ); -const size_t mbedtls_test_ca_pwd_ec_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; -const size_t mbedtls_test_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); -const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); -const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); -#else -#define TEST_CA_CRT_EC #endif /* MBEDTLS_ECDSA_C */ #if defined(MBEDTLS_RSA_C) -#define TEST_CA_CRT_RSA \ + +#if defined(MBEDTLS_SHA256_C) +#define TEST_CA_CRT_RSA_SHA256 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTcwNTA0MTY1NzAxWhcNMjcwNTA1MTY1NzAxWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/MGMGA1UdIwRcMFqA\r\n" \ +"FLRa5KWz3tJS9rnVppUP6z68x/3/oT+kPTA7MQswCQYDVQQGEwJOTDERMA8GA1UE\r\n" \ +"CgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0GCAQAwDAYDVR0T\r\n" \ +"BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAHK/HHrTZMnnVMpde1io+voAtql7j\r\n" \ +"4sRhLrjD7o3THtwRbDa2diCvpq0Sq23Ng2LMYoXsOxoL/RQK3iN7UKxV3MKPEr0w\r\n" \ +"XQS+kKQqiT2bsfrjnWMVHZtUOMpm6FNqcdGm/Rss3vKda2lcKl8kUnq/ylc1+QbB\r\n" \ +"G6A6tUvQcr2ZyWfVg+mM5XkhTrOOXus2OLikb4WwEtJTJRNE0f+yPODSUz0/vT57\r\n" \ +"ApH0CnB80bYJshYHPHHymOtleAB8KSYtqm75g/YNobjnjB6cm4HkW3OZRVIl6fYY\r\n" \ +"n20NRVA1Vjs6GAROr4NqW4k/+LofY9y0LLDE+p0oIEKXIsIvhPr39swxSA==\r\n" \ +"-----END CERTIFICATE-----\r\n" + +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA256; +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +#define TEST_CA_CRT_RSA_SOME + +static const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; + +#endif + +#if !defined(TEST_CA_CRT_RSA_SOME) || defined(MBEDTLS_SHA1_C) +#define TEST_CA_CRT_RSA_SHA1 \ "-----BEGIN CERTIFICATE-----\r\n" \ "MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ "MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ @@ -141,7 +172,15 @@ const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); "m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ "7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ "-----END CERTIFICATE-----\r\n" -const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; + +#if !defined (TEST_CA_CRT_RSA_SOME) +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA1; +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +#endif + +static const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; + +#endif const char mbedtls_test_ca_key_rsa[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" @@ -174,15 +213,18 @@ const char mbedtls_test_ca_key_rsa[] = "wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" "P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" "-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; +const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +/* tests/data_files/server2.crt */ const char mbedtls_test_srv_crt_rsa[] = "-----BEGIN CERTIFICATE-----\r\n" "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" "MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" +"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" @@ -190,15 +232,17 @@ const char mbedtls_test_srv_crt_rsa[] = "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" -"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" -"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" -"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" -"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" -"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" -"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" -"zhuYwjVuX6JHG0c=\r\n" +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAAFzC0rF\r\n" +"y6De8WMcdgQrEw3AhBHFjzqnxZw1ene4IBSC7lTw8rBSy3jOWQdPUWn+0y/pCeeF\r\n" +"kti6sevFdl1hLemGtd4q+T9TKEKGg3ND4ARfB5AUZZ9uEHq8WBkiwus5clGS17Qd\r\n" +"dS/TOisB59tQruLx1E1bPLtBKyqk4koC5WAULJwfpswGSyWJTpYwIpxcWE3D2tBu\r\n" +"UB6MZfXZFzWmWEOyKbeoXjXe8GBCGgHLywvYDsGQ36HSGtEsAvR2QaTLSxWYcfk1\r\n" +"fbDn4jSWkb4yZy1r01UEigFQtONieGwRFaUqEcFJHJvEEGVgh9keaVlOj2vrwf5r\r\n" +"4mN4lW7gLdenN6g=\r\n" "-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); +/* tests/data_files/server2.key */ const char mbedtls_test_srv_key_rsa[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" @@ -227,13 +271,15 @@ const char mbedtls_test_srv_key_rsa[] = "4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" "TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" "-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); +/* tests/data_files/cli-rsa-sha256.crt */ const char mbedtls_test_cli_crt_rsa[] = "-----BEGIN CERTIFICATE-----\r\n" -"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTEwMjEyMTQ0NDA3WhcNMjEwMjEyMTQ0NDA3WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" +"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" "1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" @@ -241,15 +287,17 @@ const char mbedtls_test_cli_crt_rsa[] = "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" "o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" -"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n" -"AQEAAn86isAM8X+mVwJqeItt6E9slhEQbAofyk+diH1Lh8Y9iLlWQSKbw/UXYjx5\r\n" -"LLPZcniovxIcARC/BjyZR9g3UwTHNGNm+rwrqa15viuNOFBchykX/Orsk02EH7NR\r\n" -"Alw5WLPorYjED6cdVQgBl9ot93HdJogRiXCxErM7NC8/eP511mjq+uLDjLKH8ZPQ\r\n" -"8I4ekHJnroLsDkIwXKGIsvIBHQy2ac/NwHLCQOK6mfum1pRx52V4Utu5dLLjD5bM\r\n" -"xOBC7KU4xZKuMXXZM6/93Yb51K/J4ahf1TxJlTWXtnzDr9saEYdNy2SKY/6ZiDNH\r\n" -"D+stpAKiQLAWaAusIWKYEyw9MQ==\r\n" +"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n" +"AQEAlHabem2Tu69VUN7EipwnQn1dIHdgvT5i+iQHpSxY1crPnBbAeSdAXwsVEqLQ\r\n" +"gOOIAQD5VIITNuoGgo4i+4OpNh9u7ZkpRHla+/swsfrFWRRbBNP5Bcu74AGLstwU\r\n" +"zM8gIkBiyfM1Q1qDQISV9trlCG6O8vh8dp/rbI3rfzo99BOHXgFCrzXjCuW4vDsF\r\n" +"r+Dao26bX3sJ6UnEWg1H3o2x6PpUcvQ36h71/bz4TEbbUUEpe02V4QWuL+wrhHJL\r\n" +"U7o3SVE3Og7jPF8sat0a50YUWhwEFI256m02KAXLg89ueUyYKEr6rNwhcvXJpvU9\r\n" +"giIVvd0Sbjjnn7NC4VDbcXV8vw==\r\n" "-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); +/* tests/data_files/cli-rsa.key */ const char mbedtls_test_cli_key_rsa[] = "-----BEGIN RSA PRIVATE KEY-----\r\n" "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" @@ -278,28 +326,32 @@ const char mbedtls_test_cli_key_rsa[] = "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" "-----END RSA PRIVATE KEY-----\r\n"; - -const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); -const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); -const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; -const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); -const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); -const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); const size_t mbedtls_test_cli_key_rsa_len = sizeof( mbedtls_test_cli_key_rsa ); -#else -#define TEST_CA_CRT_RSA #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PEM_PARSE_C) /* Concatenation of all available CA certificates */ -const char mbedtls_test_cas_pem[] = TEST_CA_CRT_RSA TEST_CA_CRT_EC; +const char mbedtls_test_cas_pem[] = +#ifdef TEST_CA_CRT_RSA_SHA1 + TEST_CA_CRT_RSA_SHA1 +#endif +#ifdef TEST_CA_CRT_RSA_SHA256 + TEST_CA_CRT_RSA_SHA256 +#endif +#ifdef TEST_CA_CRT_EC + TEST_CA_CRT_EC +#endif + ""; const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); #endif /* List of all available CA certificates */ const char * mbedtls_test_cas[] = { -#if defined(MBEDTLS_RSA_C) - mbedtls_test_ca_crt_rsa, +#if defined(TEST_CA_CRT_RSA_SHA1) + mbedtls_test_ca_crt_rsa_sha1, +#endif +#if defined(TEST_CA_CRT_RSA_SHA256) + mbedtls_test_ca_crt_rsa_sha256, #endif #if defined(MBEDTLS_ECDSA_C) mbedtls_test_ca_crt_ec, @@ -307,8 +359,11 @@ const char * mbedtls_test_cas[] = { NULL }; const size_t mbedtls_test_cas_len[] = { -#if defined(MBEDTLS_RSA_C) - sizeof( mbedtls_test_ca_crt_rsa ), +#if defined(TEST_CA_CRT_RSA_SHA1) + sizeof( mbedtls_test_ca_crt_rsa_sha1 ), +#endif +#if defined(TEST_CA_CRT_RSA_SHA256) + sizeof( mbedtls_test_ca_crt_rsa_sha256 ), #endif #if defined(MBEDTLS_ECDSA_C) sizeof( mbedtls_test_ca_crt_ec ), @@ -317,7 +372,7 @@ const size_t mbedtls_test_cas_len[] = { }; #if defined(MBEDTLS_RSA_C) -const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; /* SHA1 or SHA256 */ const char *mbedtls_test_ca_key = mbedtls_test_ca_key_rsa; const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_rsa; const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_rsa; diff --git a/Externals/mbedtls/library/chacha20.c b/Externals/mbedtls/library/chacha20.c new file mode 100644 index 0000000000..0757163e2f --- /dev/null +++ b/Externals/mbedtls/library/chacha20.c @@ -0,0 +1,570 @@ +/** + * \file chacha20.c + * + * \brief ChaCha20 cipher. + * + * \author Daniel King + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CHACHA20_C) + +#include "mbedtls/chacha20.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHA20_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define CHACHA20_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) +#define CHACHA20_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) data[offset] \ + | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \ + ) + +#define ROTL32( value, amount ) \ + ( (uint32_t) ( value << amount ) | ( value >> ( 32 - amount ) ) ) + +#define CHACHA20_CTR_INDEX ( 12U ) + +#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) + +/** + * \brief ChaCha20 quarter round operation. + * + * The quarter round is defined as follows (from RFC 7539): + * 1. a += b; d ^= a; d <<<= 16; + * 2. c += d; b ^= c; b <<<= 12; + * 3. a += b; d ^= a; d <<<= 8; + * 4. c += d; b ^= c; b <<<= 7; + * + * \param state ChaCha20 state to modify. + * \param a The index of 'a' in the state. + * \param b The index of 'b' in the state. + * \param c The index of 'c' in the state. + * \param d The index of 'd' in the state. + */ +static inline void chacha20_quarter_round( uint32_t state[16], + size_t a, + size_t b, + size_t c, + size_t d ) +{ + /* a += b; d ^= a; d <<<= 16; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 16 ); + + /* c += d; b ^= c; b <<<= 12 */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 12 ); + + /* a += b; d ^= a; d <<<= 8; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 8 ); + + /* c += d; b ^= c; b <<<= 7; */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 7 ); +} + +/** + * \brief Perform the ChaCha20 inner block operation. + * + * This function performs two rounds: the column round and the + * diagonal round. + * + * \param state The ChaCha20 state to update. + */ +static void chacha20_inner_block( uint32_t state[16] ) +{ + chacha20_quarter_round( state, 0, 4, 8, 12 ); + chacha20_quarter_round( state, 1, 5, 9, 13 ); + chacha20_quarter_round( state, 2, 6, 10, 14 ); + chacha20_quarter_round( state, 3, 7, 11, 15 ); + + chacha20_quarter_round( state, 0, 5, 10, 15 ); + chacha20_quarter_round( state, 1, 6, 11, 12 ); + chacha20_quarter_round( state, 2, 7, 8, 13 ); + chacha20_quarter_round( state, 3, 4, 9, 14 ); +} + +/** + * \brief Generates a keystream block. + * + * \param initial_state The initial ChaCha20 state (key, nonce, counter). + * \param keystream Generated keystream bytes are written to this buffer. + */ +static void chacha20_block( const uint32_t initial_state[16], + unsigned char keystream[64] ) +{ + uint32_t working_state[16]; + size_t i; + + memcpy( working_state, + initial_state, + CHACHA20_BLOCK_SIZE_BYTES ); + + for( i = 0U; i < 10U; i++ ) + chacha20_inner_block( working_state ); + + working_state[ 0] += initial_state[ 0]; + working_state[ 1] += initial_state[ 1]; + working_state[ 2] += initial_state[ 2]; + working_state[ 3] += initial_state[ 3]; + working_state[ 4] += initial_state[ 4]; + working_state[ 5] += initial_state[ 5]; + working_state[ 6] += initial_state[ 6]; + working_state[ 7] += initial_state[ 7]; + working_state[ 8] += initial_state[ 8]; + working_state[ 9] += initial_state[ 9]; + working_state[10] += initial_state[10]; + working_state[11] += initial_state[11]; + working_state[12] += initial_state[12]; + working_state[13] += initial_state[13]; + working_state[14] += initial_state[14]; + working_state[15] += initial_state[15]; + + for( i = 0U; i < 16; i++ ) + { + size_t offset = i * 4U; + + keystream[offset ] = (unsigned char)( working_state[i] ); + keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 ); + keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 ); + keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 ); + } + + mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); +} + +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) +{ + CHACHA20_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; +} + +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); + } +} + +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( key != NULL ); + + /* ChaCha20 constants - the string "expand 32-byte k" */ + ctx->state[0] = 0x61707865; + ctx->state[1] = 0x3320646e; + ctx->state[2] = 0x79622d32; + ctx->state[3] = 0x6b206574; + + /* Set key */ + ctx->state[4] = BYTES_TO_U32_LE( key, 0 ); + ctx->state[5] = BYTES_TO_U32_LE( key, 4 ); + ctx->state[6] = BYTES_TO_U32_LE( key, 8 ); + ctx->state[7] = BYTES_TO_U32_LE( key, 12 ); + ctx->state[8] = BYTES_TO_U32_LE( key, 16 ); + ctx->state[9] = BYTES_TO_U32_LE( key, 20 ); + ctx->state[10] = BYTES_TO_U32_LE( key, 24 ); + ctx->state[11] = BYTES_TO_U32_LE( key, 28 ); + + return( 0 ); +} + +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + + /* Counter */ + ctx->state[12] = counter; + + /* Nonce */ + ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 ); + ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 ); + ctx->state[15] = BYTES_TO_U32_LE( nonce, 8 ); + + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + + return( 0 ); +} + +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ) +{ + size_t offset = 0U; + size_t i; + + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || output != NULL ); + + /* Use leftover keystream bytes, if available */ + while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) + { + output[offset] = input[offset] + ^ ctx->keystream8[ctx->keystream_bytes_used]; + + ctx->keystream_bytes_used++; + offset++; + size--; + } + + /* Process full blocks */ + while( size >= CHACHA20_BLOCK_SIZE_BYTES ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < 64U; i += 8U ) + { + output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; + output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; + output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; + output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; + output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; + output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; + output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; + output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; + } + + offset += CHACHA20_BLOCK_SIZE_BYTES; + size -= CHACHA20_BLOCK_SIZE_BYTES; + } + + /* Last (partial) block */ + if( size > 0U ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < size; i++) + { + output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; + } + + ctx->keystream_bytes_used = size; + + } + + return( 0 ); +} + +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t data_len, + const unsigned char* input, + unsigned char* output ) +{ + mbedtls_chacha20_context ctx; + int ret; + + CHACHA20_VALIDATE_RET( key != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL ); + + mbedtls_chacha20_init( &ctx ); + + ret = mbedtls_chacha20_setkey( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); + +cleanup: + mbedtls_chacha20_free( &ctx ); + return( ret ); +} + +#endif /* !MBEDTLS_CHACHA20_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + } +}; + +static const unsigned char test_nonces[2][12] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02 + } +}; + +static const uint32_t test_counters[2] = +{ + 0U, + 1U +}; + +static const unsigned char test_input[2][375] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f + } +}; + +static const unsigned char test_output[2][375] = +{ + { + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, + 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, + 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, + 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, + 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, + 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, + 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 + }, + { + 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, + 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, + 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, + 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, + 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, + 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, + 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, + 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, + 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, + 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, + 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, + 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, + 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, + 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, + 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, + 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, + 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, + 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, + 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, + 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, + 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, + 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, + 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, + 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, + 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, + 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, + 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, + 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, + 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, + 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, + 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, + 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, + 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, + 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, + 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, + 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, + 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, + 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, + 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, + 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, + 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, + 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, + 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, + 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, + 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, + 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, + 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 + } +}; + +static const size_t test_lengths[2] = +{ + 64U, + 375U +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chacha20_self_test( int verbose ) +{ + unsigned char output[381]; + unsigned i; + int ret; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20 test %u ", i ); + + ret = mbedtls_chacha20_crypt( test_keys[i], + test_nonces[i], + test_counters[i], + test_lengths[i], + test_input[i], + output ); + + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), + ( "failed (output)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_CHACHA20_C */ diff --git a/Externals/mbedtls/library/chachapoly.c b/Externals/mbedtls/library/chachapoly.c new file mode 100644 index 0000000000..dc643dd618 --- /dev/null +++ b/Externals/mbedtls/library/chachapoly.c @@ -0,0 +1,540 @@ +/** + * \file chachapoly.c + * + * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + +#include "mbedtls/chachapoly.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +/* Parameter validation macros */ +#define CHACHAPOLY_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define CHACHAPOLY_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define CHACHAPOLY_STATE_INIT ( 0 ) +#define CHACHAPOLY_STATE_AAD ( 1 ) +#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ +#define CHACHAPOLY_STATE_FINISHED ( 3 ) + +/** + * \brief Adds nul bytes to pad the AAD for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +/** + * \brief Adds nul bytes to pad the ciphertext for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) +{ + CHACHAPOLY_VALIDATE( ctx != NULL ); + + mbedtls_chacha20_init( &ctx->chacha20_ctx ); + mbedtls_poly1305_init( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_chacha20_free( &ctx->chacha20_ctx ); + mbedtls_poly1305_free( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ) +{ + int ret; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( key != NULL ); + + ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); + + return( ret ); +} + +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ) +{ + int ret; + unsigned char poly1305_key[64]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + + /* Set counter = 0, will be update to 1 when generating Poly1305 key */ + ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); + if( ret != 0 ) + goto cleanup; + + /* Generate the Poly1305 key by getting the ChaCha20 keystream output with + * counter = 0. This is the same as encrypting a buffer of zeroes. + * Only the first 256-bits (32 bytes) of the key is used for Poly1305. + * The other 256 bits are discarded. + */ + memset( poly1305_key, 0, sizeof( poly1305_key ) ); + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), + poly1305_key, poly1305_key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); + + if( ret == 0 ) + { + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_AAD; + ctx->mode = mode; + } + +cleanup: + mbedtls_platform_zeroize( poly1305_key, 64U ); + return( ret ); +} + +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + + if( ctx->state != CHACHAPOLY_STATE_AAD ) + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + + ctx->aad_len += aad_len; + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); +} + +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL ); + + if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && + ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; + + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->ciphertext_len += len; + + if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) + { + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); + if( ret != 0 ) + return( ret ); + } + else /* DECRYPT */ + { + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + } + + return( 0 ); +} + +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ) +{ + int ret; + unsigned char len_block[16]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( mac != NULL ); + + if( ctx->state == CHACHAPOLY_STATE_INIT ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) + { + ret = chachapoly_pad_ciphertext( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->state = CHACHAPOLY_STATE_FINISHED; + + /* The lengths of the AAD and ciphertext are processed by + * Poly1305 as the final 128-bit block, encoded as little-endian integers. + */ + len_block[ 0] = (unsigned char)( ctx->aad_len ); + len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 ); + len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 ); + len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 ); + len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 ); + len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 ); + len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 ); + len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 ); + len_block[ 8] = (unsigned char)( ctx->ciphertext_len ); + len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 ); + len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 ); + len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 ); + len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 ); + len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 ); + len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 ); + len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); + + return( ret ); +} + +static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, + mbedtls_chachapoly_mode_t mode, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + int ret; + + ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update( ctx, length, input, output ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_finish( ctx, tag ); + +cleanup: + return( ret ); +} + +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, + length, nonce, aad, aad_len, + input, output, tag ) ); +} + +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = chachapoly_crypt_and_tag( ctx, + MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, + aad, aad_len, input, output, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_CHACHAPOLY_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_key[1][32] = +{ + { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f + } +}; + +static const unsigned char test_nonce[1][12] = +{ + { + 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ + } +}; + +static const unsigned char test_aad[1][12] = +{ + { + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7 + } +}; + +static const size_t test_aad_len[1] = +{ + 12U +}; + +static const unsigned char test_input[1][114] = +{ + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + } +}; + +static const unsigned char test_output[1][114] = +{ + { + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 + } +}; + +static const size_t test_input_len[1] = +{ + 114U +}; + +static const unsigned char test_mac[1][16] = +{ + { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 + } +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chachapoly_self_test( int verbose ) +{ + mbedtls_chachapoly_context ctx; + unsigned i; + int ret; + unsigned char output[200]; + unsigned char mac[16]; + + for( i = 0U; i < 1U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); + + mbedtls_chachapoly_init( &ctx ); + + ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); + ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); + + ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, + test_input_len[i], + test_nonce[i], + test_aad[i], + test_aad_len[i], + test_input[i], + output, + mac ); + + ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), + ( "failure (wrong output)\n" ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), + ( "failure (wrong MAC)\n" ) ); + + mbedtls_chachapoly_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CHACHAPOLY_C */ diff --git a/Externals/mbedtls/library/cipher.c b/Externals/mbedtls/library/cipher.c index a88343869c..273997577b 100644 --- a/Externals/mbedtls/library/cipher.c +++ b/Externals/mbedtls/library/cipher.c @@ -33,10 +33,15 @@ #include "mbedtls/cipher.h" #include "mbedtls/cipher_internal.h" +#include "mbedtls/platform_util.h" #include #include +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif @@ -45,6 +50,10 @@ #include "mbedtls/ccm.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" #endif @@ -56,14 +65,30 @@ #define mbedtls_free free #endif -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) -#define MBEDTLS_CIPHER_MODE_STREAM -#endif +#define CIPHER_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) +#define CIPHER_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/* Compare the contents of two buffers in constant time. + * Returns 0 if the contents are bitwise identical, otherwise returns + * a non-zero value. + * This is currently only used by GCM and ChaCha20+Poly1305. + */ +static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len ) +{ + const unsigned char *p1 = (const unsigned char*) v1; + const unsigned char *p2 = (const unsigned char*) v2; + size_t i; + unsigned char diff; + + for( diff = 0, i = 0; i < len; i++ ) + diff |= p1[i] ^ p2[i]; + + return( (int)diff ); } +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ static int supported_init = 0; @@ -130,6 +155,7 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_ciph void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) { + CIPHER_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); } @@ -141,7 +167,8 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) #if defined(MBEDTLS_CMAC_C) if( ctx->cmac_ctx ) { - mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); + mbedtls_platform_zeroize( ctx->cmac_ctx, + sizeof( mbedtls_cmac_context_t ) ); mbedtls_free( ctx->cmac_ctx ); } #endif @@ -149,12 +176,13 @@ void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) if( ctx->cipher_ctx ) ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); } int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) { - if( NULL == cipher_info || NULL == ctx ) + CIPHER_VALIDATE_RET( ctx != NULL ); + if( cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); @@ -178,10 +206,16 @@ int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_in return( 0 ); } -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ) +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( key != NULL ); + CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || + operation == MBEDTLS_DECRYPT ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && @@ -194,29 +228,33 @@ int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *k ctx->operation = operation; /* - * For CFB and CTR mode always use the encryption key schedule + * For OFB, CFB and CTR mode always use the encryption key schedule */ if( MBEDTLS_ENCRYPT == operation || MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) { - return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, - ctx->key_bitlen ); + return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); } if( MBEDTLS_DECRYPT == operation ) - return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, - ctx->key_bitlen ); + return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ) + const unsigned char *iv, + size_t iv_len ) { size_t actual_iv_size; - if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); /* avoid buffer overflow in ctx->iv */ @@ -234,15 +272,31 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } - memcpy( ctx->iv, iv, actual_iv_size ); - ctx->iv_size = actual_iv_size; +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#endif + + if ( actual_iv_size != 0 ) + { + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + } return( 0 ); } int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + CIPHER_VALIDATE_RET( ctx != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); ctx->unprocessed_len = 0; @@ -250,33 +304,60 @@ int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) return( 0 ); } -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len ) { - if( NULL == ctx || NULL == ctx->cipher_info ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { - return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, - ctx->iv, ctx->iv_size, ad, ad_len ); + return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ) ); } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int result; + mbedtls_chachapoly_mode_t mode; + + mode = ( ctx->operation == MBEDTLS_ENCRYPT ) + ? MBEDTLS_CHACHAPOLY_ENCRYPT + : MBEDTLS_CHACHAPOLY_DECRYPT; + + result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ctx->iv, + mode ); + if ( result != 0 ) + return( result ); + + return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ) ); + } +#endif return( 0 ); } -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen ) { int ret; - size_t block_size = 0; + size_t block_size; - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) - { + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } *olen = 0; block_size = mbedtls_cipher_get_block_size( ctx ); @@ -301,14 +382,23 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) { *olen = ilen; - return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, - output ); + return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) + { + *olen = ilen; + return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ) ); } #endif if ( 0 == block_size ) { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); } if( input == output && @@ -325,10 +415,12 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i /* * If there is not enough data for a full block, cache it. */ - if( ( ctx->operation == MBEDTLS_DECRYPT && - ilen + ctx->unprocessed_len <= block_size ) || + if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && + ilen < block_size - ctx->unprocessed_len ) || ( ctx->operation == MBEDTLS_ENCRYPT && - ilen + ctx->unprocessed_len < block_size ) ) + ilen < block_size - ctx->unprocessed_len ) ) { memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, ilen ); @@ -369,12 +461,20 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i { if( 0 == block_size ) { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); } + /* Encryption: only cache partial blocks + * Decryption w/ padding: always keep at least one whole block + * Decryption w/o padding: only cache partial blocks + */ copy_len = ilen % block_size; - if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) + if( copy_len == 0 && + ctx->operation == MBEDTLS_DECRYPT && + NULL != ctx->add_padding) + { copy_len = block_size; + } memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), copy_len ); @@ -417,6 +517,21 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) { @@ -433,6 +548,27 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) + { + if( ctx->unprocessed_len > 0 ) { + /* We can only process an entire data unit at a time. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ); + if( ret != 0 ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_CIPHER_MODE_STREAM) if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) { @@ -516,14 +652,14 @@ static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, if( NULL == input || NULL == data_len ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - bad = 0xFF; + bad = 0x80; *data_len = 0; for( i = input_len; i > 0; i-- ) { prev_done = done; - done |= ( input[i-1] != 0 ); + done |= ( input[i - 1] != 0 ); *data_len |= ( i - 1 ) * ( done != prev_done ); - bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done ); + bad ^= input[i - 1] * ( done != prev_done ); } return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); @@ -626,19 +762,30 @@ static int get_no_padding( unsigned char *input, size_t input_len, int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen ) { - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); *olen = 0; if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || MBEDTLS_MODE_CTR == ctx->cipher_info->mode || MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_XTS == ctx->cipher_info->mode || MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) { return( 0 ); } + if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || + ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) + { + return( 0 ); + } + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) { if( ctx->unprocessed_len != 0 ) @@ -688,8 +835,8 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, /* Set output size for decryption */ if( MBEDTLS_DECRYPT == ctx->operation ) - return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), - olen ); + return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ) ); /* Set output size for encryption */ *olen = mbedtls_cipher_get_block_size( ctx ); @@ -703,10 +850,12 @@ int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ) { - if( NULL == ctx || - MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + CIPHER_VALIDATE_RET( ctx != NULL ); + + if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } @@ -750,18 +899,35 @@ int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_ciph } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ -#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len ) { - if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); if( MBEDTLS_ENCRYPT != ctx->operation ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); + return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + tag, tag_len ) ); +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != 16U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + tag ) ); + } +#endif return( 0 ); } @@ -769,20 +935,22 @@ int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ) { + unsigned char check_tag[16]; int ret; - if( NULL == ctx || NULL == ctx->cipher_info || - MBEDTLS_DECRYPT != ctx->operation ) + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_DECRYPT != ctx->operation ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } +#if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { - unsigned char check_tag[16]; - size_t i; - int diff; - if( tag_len > sizeof( check_tag ) ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); @@ -793,18 +961,38 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, } /* Check the tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); return( 0 ); } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + check_tag ); + if ( ret != 0 ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( 0 ); } -#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /* * Packet-oriented wrapper for non-AEAD modes @@ -817,6 +1005,12 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, int ret; size_t finish_olen; + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) return( ret ); @@ -845,6 +1039,14 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen, unsigned char *tag, size_t tag_len ) { + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + #if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { @@ -863,6 +1065,21 @@ int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, tag, tag_len ) ); } #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, + ilen, iv, ad, ad_len, input, output, tag ) ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } @@ -877,6 +1094,14 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen, const unsigned char *tag, size_t tag_len ) { + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + #if defined(MBEDTLS_GCM_C) if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) { @@ -909,6 +1134,28 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, return( ret ); } #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int ret; + + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, + iv, ad, ad_len, tag, input, output ); + + if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); } diff --git a/Externals/mbedtls/library/cipher_wrap.c b/Externals/mbedtls/library/cipher_wrap.c index dc76af8ff4..6dd8c5d3a9 100644 --- a/Externals/mbedtls/library/cipher_wrap.c +++ b/Externals/mbedtls/library/cipher_wrap.c @@ -33,6 +33,10 @@ #include "mbedtls/cipher_internal.h" +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif @@ -45,6 +49,10 @@ #include "mbedtls/camellia.h" #endif +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif @@ -53,6 +61,10 @@ #include "mbedtls/blowfish.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif @@ -138,6 +150,15 @@ static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, } #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, + iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, @@ -148,6 +169,33 @@ static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, } #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + int mode; + + switch( operation ) + { + case MBEDTLS_ENCRYPT: + mode = MBEDTLS_AES_ENCRYPT; + break; + case MBEDTLS_DECRYPT: + mode = MBEDTLS_AES_DECRYPT; + break; + default: + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_aes_crypt_xts( xts_ctx, mode, length, + data_unit, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_bitlen ) { @@ -187,9 +235,15 @@ static const mbedtls_cipher_base_t aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) aes_crypt_cfb128_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + aes_crypt_ofb_wrap, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) aes_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -204,7 +258,7 @@ static const mbedtls_cipher_info_t aes_128_ecb_info = { MBEDTLS_MODE_ECB, 128, "AES-128-ECB", - 16, + 0, 0, 16, &aes_info @@ -215,7 +269,7 @@ static const mbedtls_cipher_info_t aes_192_ecb_info = { MBEDTLS_MODE_ECB, 192, "AES-192-ECB", - 16, + 0, 0, 16, &aes_info @@ -226,7 +280,7 @@ static const mbedtls_cipher_info_t aes_256_ecb_info = { MBEDTLS_MODE_ECB, 256, "AES-256-ECB", - 16, + 0, 0, 16, &aes_info @@ -302,6 +356,41 @@ static const mbedtls_cipher_info_t aes_256_cfb128_info = { }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static const mbedtls_cipher_info_t aes_128_ofb_info = { + MBEDTLS_CIPHER_AES_128_OFB, + MBEDTLS_MODE_OFB, + 128, + "AES-128-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ofb_info = { + MBEDTLS_CIPHER_AES_192_OFB, + MBEDTLS_MODE_OFB, + 192, + "AES-192-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ofb_info = { + MBEDTLS_CIPHER_AES_256_OFB, + MBEDTLS_MODE_OFB, + 256, + "AES-256-OFB", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aes_128_ctr_info = { MBEDTLS_CIPHER_AES_128_CTR, @@ -337,6 +426,92 @@ static const mbedtls_cipher_info_t aes_256_ctr_info = { }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); +} + +static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); +} + +static void *xts_aes_ctx_alloc( void ) +{ + mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); + + if( xts_ctx != NULL ) + mbedtls_aes_xts_init( xts_ctx ); + + return( xts_ctx ); +} + +static void xts_aes_ctx_free( void *ctx ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + + if( xts_ctx == NULL ) + return; + + mbedtls_aes_xts_free( xts_ctx ); + mbedtls_free( xts_ctx ); +} + +static const mbedtls_cipher_base_t xts_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + aes_crypt_xts_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + xts_aes_setkey_enc_wrap, + xts_aes_setkey_dec_wrap, + xts_aes_ctx_alloc, + xts_aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_xts_info = { + MBEDTLS_CIPHER_AES_128_XTS, + MBEDTLS_MODE_XTS, + 256, + "AES-128-XTS", + 16, + 0, + 16, + &xts_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_xts_info = { + MBEDTLS_CIPHER_AES_256_XTS, + MBEDTLS_MODE_XTS, + 512, + "AES-256-XTS", + 16, + 0, + 16, + &xts_aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + #if defined(MBEDTLS_GCM_C) static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_bitlen ) @@ -354,9 +529,15 @@ static const mbedtls_cipher_base_t gcm_aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -417,9 +598,15 @@ static const mbedtls_cipher_base_t ccm_aes_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -544,9 +731,15 @@ static const mbedtls_cipher_base_t camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) camellia_crypt_cfb128_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) camellia_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -711,9 +904,15 @@ static const mbedtls_cipher_base_t gcm_camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -774,9 +973,15 @@ static const mbedtls_cipher_base_t ccm_camellia_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -822,6 +1027,382 @@ static const mbedtls_cipher_info_t camellia_256_ccm_info = { #endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + +static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + (void) operation; + return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static void * aria_ctx_alloc( void ) +{ + mbedtls_aria_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_aria_init( ctx ); + + return( ctx ); +} + +static void aria_ctx_free( void *ctx ) +{ + mbedtls_aria_free( (mbedtls_aria_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + aria_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aria_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aria_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aria_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aria_setkey_enc_wrap, + aria_setkey_dec_wrap, + aria_ctx_alloc, + aria_ctx_free +}; + +static const mbedtls_cipher_info_t aria_128_ecb_info = { + MBEDTLS_CIPHER_ARIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "ARIA-128-ECB", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ecb_info = { + MBEDTLS_CIPHER_ARIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "ARIA-192-ECB", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ecb_info = { + MBEDTLS_CIPHER_ARIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "ARIA-256-ECB", + 16, + 0, + 16, + &aria_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aria_128_cbc_info = { + MBEDTLS_CIPHER_ARIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "ARIA-128-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cbc_info = { + MBEDTLS_CIPHER_ARIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "ARIA-192-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cbc_info = { + MBEDTLS_CIPHER_ARIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "ARIA-256-CBC", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aria_128_cfb128_info = { + MBEDTLS_CIPHER_ARIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "ARIA-128-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cfb128_info = { + MBEDTLS_CIPHER_ARIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "ARIA-192-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cfb128_info = { + MBEDTLS_CIPHER_ARIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "ARIA-256-CFB128", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aria_128_ctr_info = { + MBEDTLS_CIPHER_ARIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "ARIA-128-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ctr_info = { + MBEDTLS_CIPHER_ARIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "ARIA-192-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ctr_info = { + MBEDTLS_CIPHER_ARIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "ARIA-256-CTR", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aria_setkey_wrap, + gcm_aria_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_gcm_info = { + MBEDTLS_CIPHER_ARIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "ARIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_gcm_info = { + MBEDTLS_CIPHER_ARIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "ARIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_gcm_info = { + MBEDTLS_CIPHER_ARIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "ARIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aria_setkey_wrap, + ccm_aria_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_ccm_info = { + MBEDTLS_CIPHER_ARIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "ARIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_info = { + MBEDTLS_CIPHER_ARIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "ARIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_info = { + MBEDTLS_CIPHER_ARIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "ARIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_ARIA_C */ + #if defined(MBEDTLS_DES_C) static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, @@ -950,9 +1531,15 @@ static const mbedtls_cipher_base_t des_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -995,9 +1582,15 @@ static const mbedtls_cipher_base_t des_ede_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1040,9 +1633,15 @@ static const mbedtls_cipher_base_t des_ede3_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1149,9 +1748,15 @@ static const mbedtls_cipher_base_t blowfish_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) blowfish_crypt_cfb64_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) blowfish_crypt_ctr_wrap, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif @@ -1259,9 +1864,15 @@ static const mbedtls_cipher_base_t arc4_base_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) arc4_crypt_stream_wrap, #endif @@ -1283,6 +1894,162 @@ static const mbedtls_cipher_info_t arc4_128_info = { }; #endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int chacha20_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + + ret = mbedtls_chacha20_update( ctx, length, input, output ); + if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( ret ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + chacha20_stream_wrap, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_STREAM, + 256, + "CHACHA20", + 12, + 0, + 1, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + +static int chachapoly_setkey_wrap( void *ctx, + const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chachapoly_ctx_alloc( void ) +{ + mbedtls_chachapoly_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chachapoly_init( ctx ); + + return( ctx ); +} + +static void chachapoly_ctx_free( void *ctx ) +{ + mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chachapoly_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chachapoly_setkey_wrap, + chachapoly_setkey_wrap, + chachapoly_ctx_alloc, + chachapoly_ctx_free +}; +static const mbedtls_cipher_info_t chachapoly_info = { + MBEDTLS_CIPHER_CHACHA20_POLY1305, + MBEDTLS_MODE_CHACHAPOLY, + 256, + "CHACHA20-POLY1305", + 12, + 0, + 1, + &chachapoly_base_info +}; +#endif /* MBEDTLS_CHACHAPOLY_C */ + #if defined(MBEDTLS_CIPHER_NULL_CIPHER) static int null_crypt_stream( void *ctx, size_t length, const unsigned char *input, @@ -1322,9 +2089,15 @@ static const mbedtls_cipher_base_t null_base_info = { #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) null_crypt_stream, #endif @@ -1362,11 +2135,20 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, #endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, + { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, + { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, +#endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, #endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, + { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, +#endif #if defined(MBEDTLS_GCM_C) { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, @@ -1427,6 +2209,37 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = #endif #endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, + { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, + { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, + { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, + { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, + { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, + { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, + { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, + { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, +#endif +#endif /* MBEDTLS_ARIA_C */ + #if defined(MBEDTLS_DES_C) { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, @@ -1438,6 +2251,14 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = #endif #endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, +#endif + #if defined(MBEDTLS_CIPHER_NULL_CIPHER) { MBEDTLS_CIPHER_NULL, &null_cipher_info }, #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ diff --git a/Externals/mbedtls/library/cmac.c b/Externals/mbedtls/library/cmac.c index 199d3bcb6b..5d101e1c7d 100644 --- a/Externals/mbedtls/library/cmac.c +++ b/Externals/mbedtls/library/cmac.c @@ -1,4 +1,4 @@ -/* +/** * \file cmac.c * * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES @@ -49,6 +49,7 @@ #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" +#include "mbedtls/platform_util.h" #include @@ -62,13 +63,10 @@ #if defined(MBEDTLS_SELF_TEST) #include #define mbedtls_printf printf -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C || MBEDTLS_DES_C */ +#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_PLATFORM_C */ -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} +#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) /* * Multiplication by u in the Galois field of GF(2^n) @@ -80,7 +78,7 @@ static void mbedtls_zeroize( void *v, size_t n ) { * with R_64 = 0x1B and R_128 = 0x87 * * Input and output MUST NOT point to the same buffer - * Block size must be 8 byes or 16 bytes - the block sizes for DES and AES. + * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. */ static int cmac_multiply_by_u( unsigned char *output, const unsigned char *input, @@ -105,7 +103,7 @@ static int cmac_multiply_by_u( unsigned char *output, return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } - for( i = blocksize - 1; i >= 0; i-- ) + for( i = (int)blocksize - 1; i >= 0; i-- ) { output[i] = input[i] << 1 | overflow; overflow = input[i] >> 7; @@ -142,7 +140,7 @@ static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; size_t olen, block_size; - mbedtls_zeroize( L, sizeof( L ) ); + mbedtls_platform_zeroize( L, sizeof( L ) ); block_size = ctx->cipher_info->block_size; @@ -160,19 +158,21 @@ static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, goto exit; exit: - mbedtls_zeroize( L, sizeof( L ) ); + mbedtls_platform_zeroize( L, sizeof( L ) ); return( ret ); } +#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ +#if !defined(MBEDTLS_CMAC_ALT) static void cmac_xor_block( unsigned char *output, const unsigned char *input1, const unsigned char *input2, const size_t block_size ) { - size_t index; + size_t idx; - for( index = 0; index < block_size; index++ ) - output[ index ] = input1[ index ] ^ input2[ index ]; + for( idx = 0; idx < block_size; idx++ ) + output[ idx ] = input1[ idx ] ^ input2[ idx ]; } /* @@ -209,7 +209,7 @@ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - if( ( retval = mbedtls_cipher_setkey( ctx, key, keybits, + if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, MBEDTLS_ENCRYPT ) ) != 0 ) return( retval ); @@ -234,7 +234,7 @@ int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, ctx->cmac_ctx = cmac_ctx; - mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); return 0; } @@ -244,8 +244,8 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, { mbedtls_cmac_context_t* cmac_ctx; unsigned char *state; - int n, j, ret = 0; - size_t olen, block_size; + int ret = 0; + size_t n, j, olen, block_size; if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || ctx->cmac_ctx == NULL ) @@ -280,8 +280,9 @@ int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, /* n is the number of blocks including any final partial block */ n = ( ilen + block_size - 1 ) / block_size; - /* Iterate across the input data in block sized chunks */ - for( j = 0; j < n - 1; j++ ) + /* Iterate across the input data in block sized chunks, excluding any + * final partial or complete block */ + for( j = 1; j < n; j++ ) { cmac_xor_block( state, input, state, block_size ); @@ -325,8 +326,8 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, block_size = ctx->cipher_info->block_size; state = cmac_ctx->state; - mbedtls_zeroize( K1, sizeof( K1 ) ); - mbedtls_zeroize( K2, sizeof( K2 ) ); + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); cmac_generate_subkeys( ctx, K1, K2 ); last_block = cmac_ctx->unprocessed_block; @@ -356,14 +357,14 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, exit: /* Wipe the generated keys on the stack, and any other transients to avoid * side channel leakage */ - mbedtls_zeroize( K1, sizeof( K1 ) ); - mbedtls_zeroize( K2, sizeof( K2 ) ); + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); cmac_ctx->unprocessed_len = 0; - mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); - mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); return( ret ); } @@ -378,10 +379,10 @@ int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) /* Reset the internal state */ cmac_ctx->unprocessed_len = 0; - mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block ) ); - mbedtls_zeroize( cmac_ctx->state, - sizeof( cmac_ctx->state ) ); + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); return( 0 ); } @@ -461,12 +462,14 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, output ); exit: - mbedtls_zeroize( int_key, sizeof( int_key ) ); + mbedtls_platform_zeroize( int_key, sizeof( int_key ) ); return( ret ); } #endif /* MBEDTLS_AES_C */ +#endif /* !MBEDTLS_CMAC_ALT */ + #if defined(MBEDTLS_SELF_TEST) /* * CMAC test data for SP800-38B @@ -764,7 +767,7 @@ static int cmac_test_subkeys( int verbose, int block_size, int num_tests ) { - int i, ret; + int i, ret = 0; mbedtls_cipher_context_t ctx; const mbedtls_cipher_info_t *cipher_info; unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; @@ -825,6 +828,7 @@ static int cmac_test_subkeys( int verbose, mbedtls_cipher_free( &ctx ); } + ret = 0; goto exit; cleanup: @@ -846,7 +850,7 @@ static int cmac_test_wth_cipher( int verbose, int num_tests ) { const mbedtls_cipher_info_t *cipher_info; - int i, ret; + int i, ret = 0; unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; cipher_info = mbedtls_cipher_info_from_type( cipher_type ); @@ -880,6 +884,7 @@ static int cmac_test_wth_cipher( int verbose, if( verbose != 0 ) mbedtls_printf( "passed\n" ); } + ret = 0; exit: return( ret ); diff --git a/Externals/mbedtls/library/ctr_drbg.c b/Externals/mbedtls/library/ctr_drbg.c index 386f8adb07..fb121575bb 100644 --- a/Externals/mbedtls/library/ctr_drbg.c +++ b/Externals/mbedtls/library/ctr_drbg.c @@ -19,7 +19,7 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ /* - * The NIST SP 800-90 DRBGs are described in the following publucation. + * The NIST SP 800-90 DRBGs are described in the following publication. * * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf */ @@ -33,6 +33,7 @@ #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" +#include "mbedtls/platform_util.h" #include @@ -49,11 +50,6 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * CTR_DRBG context initialization */ @@ -70,6 +66,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow * NIST tests to succeed (which require known length fixed entropy) */ +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy, + * custom, len, entropy_len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * custom[:len] = nonce || personalization_string + * where entropy_input comes from f_entropy for entropy_len bytes + * and with outputs + * ctx = initial_working_state + */ int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), @@ -94,11 +102,15 @@ int mbedtls_ctr_drbg_seed_entropy_len( /* * Initialize with an empty key */ - mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + { return( ret ); - + } return( 0 ); } @@ -121,7 +133,7 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) mbedtls_mutex_free( &ctx->mutex ); #endif mbedtls_aes_free( &ctx->aes_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); } void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) @@ -148,6 +160,7 @@ static int block_cipher_df( unsigned char *output, unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; unsigned char *p, *iv; mbedtls_aes_context aes_ctx; + int ret = 0; int i, j; size_t buf_len, use_len; @@ -180,7 +193,10 @@ static int block_cipher_df( unsigned char *output, for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) key[i] = i; - mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } /* * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data @@ -199,7 +215,10 @@ static int block_cipher_df( unsigned char *output, use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; - mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ); + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 ) + { + goto exit; + } } memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); @@ -213,28 +232,57 @@ static int block_cipher_df( unsigned char *output, /* * Do final encryption with reduced data */ - mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; p = output; for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) { - mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) + { + goto exit; + } memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } - +exit: mbedtls_aes_free( &aes_ctx ); + /* + * tidy up the stack + */ + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( chain, sizeof( chain ) ); + if( 0 != ret ) + { + /* + * wipe partial seed from memory + */ + mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + } - return( 0 ); + return( ret ); } +/* CTR_DRBG_Update (SP 800-90A §10.2.1.2) + * ctr_drbg_update_internal(ctx, provided_data) + * implements + * CTR_DRBG_Update(provided_data, Key, V) + * with inputs and outputs + * ctx->aes_ctx = Key + * ctx->counter = V + */ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) { unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char *p = tmp; int i, j; + int ret = 0; memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); @@ -250,7 +298,8 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, /* * Crypt counter block */ - mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ); + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) + goto exit; p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } @@ -261,36 +310,81 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, /* * Update key and counter */ - mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + goto exit; memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - return( 0 ); +exit: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); } -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_update(ctx, additional, add_len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * ctx->counter = all-bits-0 + * ctx->aes_ctx = context from all-bits-0 key + * additional[:add_len] = entropy_input || nonce || personalization_string + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) { unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + int ret; - if( add_len > 0 ) - { - /* MAX_INPUT would be more logical here, but we have to match - * block_cipher_df()'s limits since we can't propagate errors */ - if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) - add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + if( add_len == 0 ) + return( 0 ); - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); - } + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) + * mbedtls_ctr_drbg_reseed(ctx, additional, len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) + * -> new_working_state + * with inputs + * ctx contains working_state + * additional[:len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with output + * ctx contains new_working_state + */ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len ) { unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; size_t seedlen = 0; + int ret; - if( ctx->entropy_len + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); @@ -318,17 +412,40 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, /* * Reduce to 384 bits */ - block_cipher_df( seed, seed, seedlen ); + if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) + goto exit; /* * Update state */ - ctr_drbg_update_internal( ctx, seed ); + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + goto exit; ctx->reseed_counter = 1; - return( 0 ); +exit: + mbedtls_platform_zeroize( seed, sizeof( seed ) ); + return( ret ); } +/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) + * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) + * -> working_state_after_reseed + * if required, then + * CTR_DRBG_Generate(working_state_after_reseed, + * requested_number_of_bits, additional_input) + * -> status, returned_bits, new_working_state + * with inputs + * ctx contains working_state + * requested_number_of_bits = 8 * output_len + * additional[:add_len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with outputs + * status = SUCCESS (this function does the reseed internally) + * returned_bits = output[:output_len] + * ctx contains new_working_state + */ int mbedtls_ctr_drbg_random_with_add( void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len ) @@ -353,15 +470,18 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, ctx->prediction_resistance ) { if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + { return( ret ); - + } add_len = 0; } if( add_len > 0 ) { - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; } while( output_len > 0 ) @@ -376,7 +496,8 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, /* * Crypt counter block */ - mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ); + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) + goto exit; use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; @@ -388,10 +509,14 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, output_len -= use_len; } - ctr_drbg_update_internal( ctx, add_input ); + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; ctx->reseed_counter++; +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); return( 0 ); } @@ -429,47 +554,50 @@ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char goto exit; if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) - { ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; - goto exit; - } - - ret = 0; + else + ret = 0; exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); return( ret ); } int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) { - FILE *f; + int ret = 0; + FILE *f = NULL; size_t n; unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + unsigned char c; if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_CTR_DRBG_MAX_INPUT ) + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) { - fclose( f ); - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; + goto exit; } - - if( fread( buf, 1, n, f ) != n ) + if( n == 0 || ferror( f ) ) { - fclose( f ); - return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + goto exit; } - fclose( f ); + f = NULL; - mbedtls_ctr_drbg_update( ctx, buf, n ); + ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); } #endif /* MBEDTLS_FS_IO */ diff --git a/Externals/mbedtls/library/debug.c b/Externals/mbedtls/library/debug.c index a9cd814be4..824cd0236e 100644 --- a/Externals/mbedtls/library/debug.c +++ b/Externals/mbedtls/library/debug.c @@ -71,7 +71,7 @@ static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, */ #if defined(MBEDTLS_THREADING_C) char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ - mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", ssl, str ); + mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); #else ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); @@ -91,7 +91,7 @@ void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, va_start( argp, format ); #if defined(_WIN32) -#if defined(_TRUNCATE) +#if defined(_TRUNCATE) && !defined(__MINGW32__) ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp ); #else ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); @@ -365,4 +365,54 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, } #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_ECDH_C) +static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl, + int level, const char *file, + int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + const mbedtls_ecdh_context* ctx = ecdh; +#else + const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh; +#endif + + switch( attr ) + { + case MBEDTLS_DEBUG_ECDH_Q: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q", + &ctx->Q ); + break; + case MBEDTLS_DEBUG_ECDH_QP: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp", + &ctx->Qp ); + break; + case MBEDTLS_DEBUG_ECDH_Z: + mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z", + &ctx->z ); + break; + default: + break; + } +} + +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr ); +#else + switch( ecdh->var ) + { + default: + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, + attr ); + } +#endif +} +#endif /* MBEDTLS_ECDH_C */ + #endif /* MBEDTLS_DEBUG_C */ diff --git a/Externals/mbedtls/library/des.c b/Externals/mbedtls/library/des.c index 09f95cfc3b..ca9e071f32 100644 --- a/Externals/mbedtls/library/des.c +++ b/Externals/mbedtls/library/des.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" +#include "mbedtls/platform_util.h" #include @@ -48,11 +49,6 @@ #if !defined(MBEDTLS_DES_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (big endian) */ @@ -316,7 +312,7 @@ void mbedtls_des_free( mbedtls_des_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_des_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) ); } void mbedtls_des3_init( mbedtls_des3_context *ctx ) @@ -329,7 +325,7 @@ void mbedtls_des3_free( mbedtls_des3_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_des3_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) ); } static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, @@ -553,7 +549,7 @@ int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, uint32_t sk[96]; des3_set2key( ctx->sk, sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); return( 0 ); } @@ -567,7 +563,7 @@ int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, uint32_t sk[96]; des3_set2key( sk, ctx->sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); return( 0 ); } @@ -604,7 +600,7 @@ int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, uint32_t sk[96]; des3_set3key( ctx->sk, sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); return( 0 ); } @@ -618,7 +614,7 @@ int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, uint32_t sk[96]; des3_set3key( sk, ctx->sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); return( 0 ); } diff --git a/Externals/mbedtls/library/dhm.c b/Externals/mbedtls/library/dhm.c index a4715d1703..fb6937e854 100644 --- a/Externals/mbedtls/library/dhm.c +++ b/Externals/mbedtls/library/dhm.c @@ -36,6 +36,7 @@ #if defined(MBEDTLS_DHM_C) #include "mbedtls/dhm.h" +#include "mbedtls/platform_util.h" #include @@ -57,10 +58,12 @@ #define mbedtls_free free #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +#if !defined(MBEDTLS_DHM_ALT) + +#define DHM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA ) +#define DHM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) /* * helper to validate the mbedtls_mpi size and import it @@ -93,6 +96,9 @@ static int dhm_read_bignum( mbedtls_mpi *X, * * Parameter should be: 2 <= public_param <= P - 2 * + * This means that we need to return an error if + * public_param < 2 or public_param > P-2 + * * For more information on the attack, see: * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 @@ -100,17 +106,17 @@ 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; - int ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + int ret = 0; mbedtls_mpi_init( &L ); 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 && - mbedtls_mpi_cmp_mpi( param, &U ) <= 0 ) + if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 || + mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) { - ret = 0; + ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } cleanup: @@ -120,6 +126,7 @@ cleanup: void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) { + DHM_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); } @@ -131,6 +138,9 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, const unsigned char *end ) { int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( p != NULL && *p != NULL ); + DHM_VALIDATE_RET( end != NULL ); if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || @@ -156,6 +166,10 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, 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 ); if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); @@ -165,7 +179,7 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, */ do { - mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); + 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 ) ); @@ -187,10 +201,15 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, /* * export P, G, GX */ -#define DHM_MPI_EXPORT(X,n) \ - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, p + 2, n ) ); \ - *p++ = (unsigned char)( n >> 8 ); \ - *p++ = (unsigned char)( n ); p += n; +#define DHM_MPI_EXPORT( X, n ) \ + do { \ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ + p + 2, \ + ( n ) ) ); \ + *p++ = (unsigned char)( ( n ) >> 8 ); \ + *p++ = (unsigned char)( ( n ) ); \ + p += ( n ); \ + } while( 0 ) n1 = mbedtls_mpi_size( &ctx->P ); n2 = mbedtls_mpi_size( &ctx->G ); @@ -201,7 +220,7 @@ int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, DHM_MPI_EXPORT( &ctx->G , n2 ); DHM_MPI_EXPORT( &ctx->GX, n3 ); - *olen = p - output; + *olen = p - output; ctx->len = n1; @@ -213,6 +232,28 @@ cleanup: return( 0 ); } +/* + * Set prime modulus and generator + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ) +{ + int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( P != NULL ); + DHM_VALIDATE_RET( G != NULL ); + + if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) + { + return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->P ); + return( 0 ); +} + /* * Import the peer's public value G^Y */ @@ -220,8 +261,10 @@ int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen ) { int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( input != NULL ); - if( ctx == NULL || ilen < 1 || ilen > ctx->len ) + if( ilen < 1 || ilen > ctx->len ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) @@ -239,8 +282,11 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, void *p_rng ) { int ret, count = 0; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); - if( ctx == NULL || olen < 1 || olen > ctx->len ) + if( olen < 1 || olen > ctx->len ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) @@ -251,7 +297,7 @@ int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, */ do { - mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ); + 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 ) ); @@ -324,7 +370,7 @@ static int dhm_update_blinding( mbedtls_dhm_context *ctx, count = 0; do { - mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ); + 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 ) ); @@ -352,8 +398,11 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, { int ret; mbedtls_mpi GYb; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); - if( ctx == NULL || output_size < ctx->len ) + if( output_size < ctx->len ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) @@ -400,12 +449,21 @@ cleanup: */ void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) { - mbedtls_mpi_free( &ctx->pX); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->Vi ); - mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); - mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); mbedtls_mpi_free( &ctx->G ); - mbedtls_mpi_free( &ctx->P ); + if( ctx == NULL ) + return; - mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); + mbedtls_mpi_free( &ctx->pX ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->K ); + mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); + mbedtls_mpi_free( &ctx->X ); + mbedtls_mpi_free( &ctx->G ); + mbedtls_mpi_free( &ctx->P ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); } #if defined(MBEDTLS_ASN1_PARSE_C) @@ -420,7 +478,12 @@ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, unsigned char *p, *end; #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_context pem; +#endif /* MBEDTLS_PEM_PARSE_C */ + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( dhmin != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init( &pem ); /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ @@ -542,7 +605,10 @@ static int load_file( const char *path, unsigned char **buf, size_t *n ) if( fread( *buf, 1, *n, f ) != *n ) { fclose( f ); + + mbedtls_platform_zeroize( *buf, *n + 1 ); mbedtls_free( *buf ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); } @@ -564,19 +630,22 @@ int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) int ret; size_t n; unsigned char *buf; + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( path != NULL ); if( ( ret = load_file( path, &buf, &n ) ) != 0 ) return( ret ); ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); } #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_DHM_ALT */ #if defined(MBEDTLS_SELF_TEST) diff --git a/Externals/mbedtls/library/ecdh.c b/Externals/mbedtls/library/ecdh.c index c0a8147312..da95c60dad 100644 --- a/Externals/mbedtls/library/ecdh.c +++ b/Externals/mbedtls/library/ecdh.c @@ -35,38 +35,82 @@ #if defined(MBEDTLS_ECDH_C) #include "mbedtls/ecdh.h" +#include "mbedtls/platform_util.h" #include +/* Parameter validation macros based on platform_util.h */ +#define ECDH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; +#endif + +#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) /* - * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair + * Generate public key (restartable version) + * + * Note: this internal function relies on its caller preserving the value of + * the output parameter 'd' across continuation calls. This would not be + * acceptable for a public function but is OK here as we control call sites. + */ +static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + + /* If multiplication is in progress, we already generated a privkey */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + return( ret ); +} + +/* + * Generate public key */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); } +#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ +#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) /* * Compute shared secret (SEC1 3.3.1) */ -int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, +static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; mbedtls_ecp_point P; mbedtls_ecp_point_init( &P ); - /* - * Make sure Q is a valid pubkey before using it - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, + f_rng, p_rng, rs_ctx ) ); if( mbedtls_ecp_is_zero( &P ) ) { @@ -82,14 +126,120 @@ cleanup: return( ret ); } +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( z != NULL ); + return( ecdh_compute_shared_restartable( grp, z, Q, d, + f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_init( &ctx->grp ); + mbedtls_mpi_init( &ctx->d ); + mbedtls_ecp_point_init( &ctx->Q ); + mbedtls_ecp_point_init( &ctx->Qp ); + mbedtls_mpi_init( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_init( &ctx->rs ); +#endif +} + /* * Initialize context */ void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) { + ECDH_VALIDATE( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + ecdh_init_internal( ctx ); + mbedtls_ecp_point_init( &ctx->Vi ); + mbedtls_ecp_point_init( &ctx->Vf ); + mbedtls_mpi_init( &ctx->_d ); +#else memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); + + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; +#endif + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + ctx->restart_enabled = 0; +#endif } +static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, + mbedtls_ecp_group_id grp_id ) +{ + int ret; + + ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); + if( ret != 0 ) + { + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +/* + * Setup context + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_setup_internal( ctx, grp_id ) ); +#else + switch( grp_id ) + { + default: + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; + ctx->grp_id = grp_id; + ecdh_init_internal( &ctx->ctx.mbed_ecdh ); + return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); + } +#endif +} + +static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_mpi_free( &ctx->d ); + mbedtls_ecp_point_free( &ctx->Q ); + mbedtls_ecp_point_free( &ctx->Qp ); + mbedtls_mpi_free( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_free( &ctx->rs ); +#endif +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Enable restartable operations for context + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + + ctx->restart_enabled = 1; +} +#endif + /* * Free context */ @@ -98,14 +248,76 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) if( ctx == NULL ) return; - mbedtls_ecp_group_free( &ctx->grp ); - mbedtls_ecp_point_free( &ctx->Q ); - mbedtls_ecp_point_free( &ctx->Qp ); - mbedtls_ecp_point_free( &ctx->Vi ); - mbedtls_ecp_point_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->d ); - mbedtls_mpi_free( &ctx->z ); +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_point_free( &ctx->Vi ); + mbedtls_ecp_point_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->_d ); + ecdh_free_internal( ctx ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + ecdh_free_internal( &ctx->ctx.mbed_ecdh ); + break; + default: + break; + } + + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; + ctx->grp_id = MBEDTLS_ECP_DP_NONE; +#endif +} + +static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret; + size_t grp_len, pt_len; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, + blen ) ) != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, + &pt_len, buf, blen ) ) != 0 ) + return( ret ); + + *olen = grp_len + pt_len; + return( 0 ); } /* @@ -116,33 +328,45 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) * } ServerECDHParams; */ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { - int ret; - size_t grp_len, pt_len; + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); - if( ctx == NULL || ctx->grp.pbits == 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#else + (void) restart_enabled; +#endif - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) - return( ret ); +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} - if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) - != 0 ) - return( ret ); - - buf += grp_len; - blen -= grp_len; - - if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - &pt_len, buf, blen ) ) != 0 ) - return( ret ); - - *olen = grp_len + pt_len; - return( 0 ); +static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, + end - *buf ) ); } /* @@ -153,31 +377,43 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, * } ServerECDHParams; */ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, - const unsigned char **buf, const unsigned char *end ) + const unsigned char **buf, + const unsigned char *end ) { int ret; + mbedtls_ecp_group_id grp_id; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( *buf != NULL ); + ECDH_VALIDATE_RET( end != NULL ); - if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) + != 0 ) return( ret ); - if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) - != 0 ) + if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) return( ret ); - return( 0 ); +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_params_internal( ctx, buf, end ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, + buf, end ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif } -/* - * Get parameters from a keypair - */ -int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, - mbedtls_ecdh_side side ) +static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) { int ret; - if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) - return( ret ); - /* If it's not our key, just import the public part as Qp */ if( side == MBEDTLS_ECDH_THEIRS ) return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); @@ -194,39 +430,116 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai } /* - * Setup and export the client public value + * Get parameters from a keypair */ -int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) { int ret; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( key != NULL ); + ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || + side == MBEDTLS_ECDH_THEIRS ); - if( ctx == NULL || ctx->grp.pbits == 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) + if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) return( ret ); - return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - olen, buf, blen ); +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_get_params_internal( ctx, key, side ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, + key, side ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, + buf, blen ); } /* - * Parse and import the client's public value + * Setup and export the client public value */ -int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, - const unsigned char *buf, size_t blen ) +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char *buf, size_t blen ) { int ret; const unsigned char *p = buf; - if( ctx == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 ) + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, + blen ) ) != 0 ) return( ret ); if( (size_t)( p - buf ) != blen ) @@ -236,23 +549,66 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, } /* - * Derive and export the shared secret + * Parse and import the client's public value */ -int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_public_internal( ctx, buf, blen ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, + buf, blen ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, unsigned char *buf, + size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) { int ret; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif - if( ctx == NULL ) + if( ctx == NULL || ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, - f_rng, p_rng ) ) != 0 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng, + rs_ctx ) ) != 0 ) { return( ret ); } +#else + if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ if( mbedtls_mpi_size( &ctx->z ) > blen ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -261,4 +617,37 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); } +/* + * Derive and export the shared secret + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, + restart_enabled ) ); +#else + switch( ctx->var ) + { + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, + blen, f_rng, p_rng, + restart_enabled ) ); + default: + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } +#endif +} + #endif /* MBEDTLS_ECDH_C */ diff --git a/Externals/mbedtls/library/ecdsa.c b/Externals/mbedtls/library/ecdsa.c index 4156f3c3c4..dc19384d61 100644 --- a/Externals/mbedtls/library/ecdsa.c +++ b/Externals/mbedtls/library/ecdsa.c @@ -42,6 +42,186 @@ #include "mbedtls/hmac_drbg.h" #endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/platform_util.h" + +/* Parameter validation macros based on platform_util.h */ +#define ECDSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/* + * Sub-context for ecdsa_verify() + */ +struct mbedtls_ecdsa_restart_ver +{ + mbedtls_mpi u1, u2; /* intermediate values */ + enum { /* what to do next? */ + ecdsa_ver_init = 0, /* getting started */ + ecdsa_ver_muladd, /* muladd step */ + } state; +}; + +/* + * Init verify restart sub-context + */ +static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + mbedtls_mpi_init( &ctx->u1 ); + mbedtls_mpi_init( &ctx->u2 ); + ctx->state = ecdsa_ver_init; +} + +/* + * Free the components of a verify restart sub-context + */ +static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->u1 ); + mbedtls_mpi_free( &ctx->u2 ); + + ecdsa_restart_ver_init( ctx ); +} + +/* + * Sub-context for ecdsa_sign() + */ +struct mbedtls_ecdsa_restart_sig +{ + int sign_tries; + int key_tries; + mbedtls_mpi k; /* per-signature random */ + mbedtls_mpi r; /* r value */ + enum { /* what to do next? */ + ecdsa_sig_init = 0, /* getting started */ + ecdsa_sig_mul, /* doing ecp_mul() */ + ecdsa_sig_modn, /* mod N computations */ + } state; +}; + +/* + * Init verify sign sub-context + */ +static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + ctx->sign_tries = 0; + ctx->key_tries = 0; + mbedtls_mpi_init( &ctx->k ); + mbedtls_mpi_init( &ctx->r ); + ctx->state = ecdsa_sig_init; +} + +/* + * Free the components of a sign restart sub-context + */ +static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->k ); + mbedtls_mpi_free( &ctx->r ); +} + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Sub-context for ecdsa_sign_det() + */ +struct mbedtls_ecdsa_restart_det +{ + mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ + enum { /* what to do next? */ + ecdsa_det_init = 0, /* getting started */ + ecdsa_det_sign, /* make signature */ + } state; +}; + +/* + * Init verify sign_det sub-context + */ +static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + mbedtls_hmac_drbg_init( &ctx->rng_ctx ); + ctx->state = ecdsa_det_init; +} + +/* + * Free the components of a sign_det restart sub-context + */ +static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_hmac_drbg_free( &ctx->rng_ctx ); + + ecdsa_restart_det_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#define ECDSA_RS_ECP &rs_ctx->ecp + +/* Utility macro for checking and updating ops budget */ +#define ECDSA_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) ); + +/* Call this when entering a function that needs its own sub-context */ +#define ECDSA_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ + rs_ctx->ecp.ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECDSA_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->ecp.depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECDSA_RS_ECP NULL + +#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ + +#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx +#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* * Derive a suitable integer for group grp from a buffer of length len * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 @@ -65,45 +245,100 @@ cleanup: return( ret ); } +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) /* * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) */ -int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, +static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { - int ret, key_tries, sign_tries, blind_tries; + int ret, key_tries, sign_tries; + int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; + mbedtls_mpi *pk = &k, *pr = r; /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + /* Make sure d is in range 1..n-1 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); - sign_tries = 0; + ECDSA_RS_ENTER( sig ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + { + /* redirect to our context */ + p_sign_tries = &rs_ctx->sig->sign_tries; + p_key_tries = &rs_ctx->sig->key_tries; + pk = &rs_ctx->sig->k; + pr = &rs_ctx->sig->r; + + /* jump to current step */ + if( rs_ctx->sig->state == ecdsa_sig_mul ) + goto mul; + if( rs_ctx->sig->state == ecdsa_sig_modn ) + goto modn; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + *p_sign_tries = 0; do { + if( *p_sign_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + /* * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n */ - key_tries = 0; + *p_key_tries = 0; do { - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); - - if( key_tries++ > 10 ) + if( *p_key_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_mul; + +mul: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, + f_rng, p_rng, ECDSA_RS_ECP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); } - while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); + while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_modn; + +modn: +#endif + /* + * Accounting for everything up to the end of the loop + * (step 6, but checking now avoids saving e and t) + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); /* * Step 5: derive MPI from hashed message @@ -114,56 +349,67 @@ int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, * Generate a random value to blind inv_mod in next step, * avoiding a potential timing leak. */ - blind_tries = 0; - do - { - size_t n_size = ( grp->nbits + 7 ) / 8; - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); - - /* See mbedtls_ecp_gen_keypair() */ - if( ++blind_tries > 30 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) ); /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); - - if( sign_tries++ > 10 ) - { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } } while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + mbedtls_mpi_copy( r, pr ); +#endif + cleanup: mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + ECDSA_RS_LEAVE( sig ); + return( ret ); } +/* + * Compute ECDSA signature of a hashed message + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_sign_restartable( grp, r, s, d, buf, blen, + f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ + #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Deterministic signature wrapper */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, +static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ) + mbedtls_md_type_t md_alg, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_hmac_drbg_context rng_ctx; + mbedtls_hmac_drbg_context *p_rng = &rng_ctx; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; size_t grp_len = ( grp->nbits + 7 ) / 8; const mbedtls_md_info_t *md_info; @@ -175,42 +421,105 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi mbedtls_mpi_init( &h ); mbedtls_hmac_drbg_init( &rng_ctx ); + ECDSA_RS_ENTER( det ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + { + /* redirect to our context */ + p_rng = &rs_ctx->det->rng_ctx; + + /* jump to current step */ + if( rs_ctx->det->state == ecdsa_det_sign ) + goto sign; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); - mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); + mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + rs_ctx->det->state = ecdsa_det_sign; + +sign: +#endif +#if defined(MBEDTLS_ECDSA_SIGN_ALT) ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, - mbedtls_hmac_drbg_random, &rng_ctx ); + mbedtls_hmac_drbg_random, p_rng ); +#else + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, rs_ctx ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ cleanup: mbedtls_hmac_drbg_free( &rng_ctx ); mbedtls_mpi_free( &h ); + ECDSA_RS_LEAVE( det ); + return( ret ); } + +/* + * Deterministic signature wrapper + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) ); +} #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) /* * Verify ECDSA signature of hashed message (SEC1 4.1.4) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) */ -int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) +static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; + mbedtls_mpi *pu1 = &u1, *pu2 = &u2; mbedtls_ecp_point_init( &R ); - mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); + mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + ECDSA_RS_ENTER( ver ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + { + /* redirect to our context */ + pu1 = &rs_ctx->ver->u1; + pu2 = &rs_ctx->ver->u2; + + /* jump to current step */ + if( rs_ctx->ver->state == ecdsa_ver_muladd ) + goto muladd; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* * Step 1: make sure r and s are in range 1..n-1 */ @@ -221,11 +530,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, goto cleanup; } - /* - * Additional precaution: make sure Q is valid - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - /* * Step 3: derive MPI from hashed message */ @@ -234,21 +538,27 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, /* * Step 4: u1 = e / s mod n, u2 = r / s mod n */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + rs_ctx->ver->state = ecdsa_ver_muladd; + +muladd: +#endif /* * Step 5: R = u1 G + u2 Q - * - * Since we're not using any secret data, no need to pass a RNG to - * mbedtls_ecp_mul() for countermesures. */ - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, + &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); if( mbedtls_ecp_is_zero( &R ) ) { @@ -273,11 +583,33 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, cleanup: mbedtls_ecp_point_free( &R ); - mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); + mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + ECDSA_RS_LEAVE( ver ); return( ret ); } +/* + * Verify ECDSA signature of hashed message + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( Q != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ + /* * Convert a signature (given by context) to ASN.1 */ @@ -305,14 +637,20 @@ static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, /* * Compute and write signature */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); @@ -321,14 +659,19 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t (void) f_rng; (void) p_rng; - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, - hash, hlen, md_alg ) ); + MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, rs_ctx ) ); #else (void) md_alg; +#if defined(MBEDTLS_ECDSA_SIGN_ALT) MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng ) ); -#endif +#else + MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng, rs_ctx ) ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); @@ -339,13 +682,35 @@ cleanup: return( ret ); } -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \ defined(MBEDTLS_ECDSA_DETERMINISTIC) int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, mbedtls_md_type_t md_alg ) { + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, NULL, NULL ) ); } @@ -357,12 +722,30 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + return( mbedtls_ecdsa_read_signature_restartable( + ctx, hash, hlen, sig, slen, NULL ) ); +} + +/* + * Restartable read and check signature + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); @@ -387,11 +770,19 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } - +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, - &ctx->Q, &r, &s ) ) != 0 ) + &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; +#else + if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ if( p != end ) ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; @@ -402,15 +793,25 @@ cleanup: return( ret ); } +#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) /* * Generate key pair */ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - return( mbedtls_ecp_group_load( &ctx->grp, gid ) || - mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); + int ret = 0; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + + ret = mbedtls_ecp_group_load( &ctx->grp, gid ); + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, + &ctx->Q, f_rng, p_rng ) ); } +#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ /* * Set context from an mbedtls_ecp_keypair @@ -418,6 +819,8 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) { int ret; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( key != NULL ); if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || @@ -434,6 +837,8 @@ int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_ke */ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) { + ECDSA_VALIDATE( ctx != NULL ); + mbedtls_ecp_keypair_init( ctx ); } @@ -442,7 +847,53 @@ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) */ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) { + if( ctx == NULL ) + return; + mbedtls_ecp_keypair_free( ctx ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_restart_init( &ctx->ecp ); + + ctx->ver = NULL; + ctx->sig = NULL; +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ctx->det = NULL; +#endif +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_restart_free( &ctx->ecp ); + + ecdsa_restart_ver_free( ctx->ver ); + mbedtls_free( ctx->ver ); + ctx->ver = NULL; + + ecdsa_restart_sig_free( ctx->sig ); + mbedtls_free( ctx->sig ); + ctx->sig = NULL; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ecdsa_restart_det_free( ctx->det ); + mbedtls_free( ctx->det ); + ctx->det = NULL; +#endif +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #endif /* MBEDTLS_ECDSA_C */ diff --git a/Externals/mbedtls/library/ecjpake.c b/Externals/mbedtls/library/ecjpake.c index 1fa1c2d801..be941b14b1 100644 --- a/Externals/mbedtls/library/ecjpake.c +++ b/Externals/mbedtls/library/ecjpake.c @@ -33,9 +33,18 @@ #if defined(MBEDTLS_ECJPAKE_C) #include "mbedtls/ecjpake.h" +#include "mbedtls/platform_util.h" #include +#if !defined(MBEDTLS_ECJPAKE_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECJPAKE_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECJPAKE_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * Convert a mbedtls_ecjpake_role to identifier string */ @@ -52,8 +61,7 @@ static const char * const ecjpake_id[] = { */ void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) { - if( ctx == NULL ) - return; + ECJPAKE_VALIDATE( ctx != NULL ); ctx->md_info = NULL; mbedtls_ecp_group_init( &ctx->grp ); @@ -104,6 +112,11 @@ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, { int ret; + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT || + role == MBEDTLS_ECJPAKE_SERVER ); + ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 ); + ctx->role = role; if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) @@ -125,6 +138,8 @@ cleanup: */ int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) { + ECJPAKE_VALIDATE_RET( ctx != NULL ); + if( ctx->md_info == NULL || ctx->grp.id == MBEDTLS_ECP_DP_NONE || ctx->s.p == NULL ) @@ -299,7 +314,7 @@ cleanup: */ static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, const mbedtls_ecp_group *grp, - const int pf, + const int pf, const mbedtls_ecp_point *G, const mbedtls_mpi *x, const mbedtls_ecp_point *X, @@ -502,6 +517,9 @@ int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len ) { + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->Xp1, &ctx->Xp2, ID_PEER, @@ -516,6 +534,11 @@ int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, @@ -558,6 +581,9 @@ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, mbedtls_ecp_group grp; mbedtls_ecp_point G; /* C: GB, S: GA */ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + mbedtls_ecp_group_init( &grp ); mbedtls_ecp_point_init( &G ); @@ -650,6 +676,11 @@ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, const unsigned char *end = buf + len; size_t ec_len; + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + mbedtls_ecp_point_init( &G ); mbedtls_ecp_point_init( &Xm ); mbedtls_mpi_init( &xm ); @@ -725,6 +756,11 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; size_t x_bytes; + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + *olen = mbedtls_md_get_size( ctx->md_info ); if( len < *olen ) return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); @@ -764,6 +800,7 @@ cleanup: #undef ID_MINE #undef ID_PEER +#endif /* ! MBEDTLS_ECJPAKE_ALT */ #if defined(MBEDTLS_SELF_TEST) diff --git a/Externals/mbedtls/library/ecp.c b/Externals/mbedtls/library/ecp.c index f51f2251ed..ecea5910e0 100644 --- a/Externals/mbedtls/library/ecp.c +++ b/Externals/mbedtls/library/ecp.c @@ -26,6 +26,7 @@ * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf * RFC 4492 for the related TLS structures and constants + * RFC 7748 for the Curve448 and Curve25519 curve definitions * * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf * @@ -46,12 +47,51 @@ #include MBEDTLS_CONFIG_FILE #endif +/** + * \brief Function level alternative implementation. + * + * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to + * replace certain functions in this module. The alternative implementations are + * typically hardware accelerators and need to activate the hardware before the + * computation starts and deactivate it after it finishes. The + * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve + * this purpose. + * + * To preserve the correct functionality the following conditions must hold: + * + * - The alternative implementation must be activated by + * mbedtls_internal_ecp_init() before any of the replaceable functions is + * called. + * - mbedtls_internal_ecp_free() must \b only be called when the alternative + * implementation is activated. + * - mbedtls_internal_ecp_init() must \b not be called when the alternative + * implementation is activated. + * - Public functions must not return while the alternative implementation is + * activated. + * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and + * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) + * \endcode ensures that the alternative implementation supports the current + * group. + */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +#endif + #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" +#include "mbedtls/threading.h" +#include "mbedtls/platform_util.h" #include +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else @@ -62,16 +102,13 @@ #define mbedtls_free free #endif +#include "mbedtls/ecp_internal.h" + #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - #if defined(MBEDTLS_SELF_TEST) /* * Counts of point addition and doubling, and field multiplications. @@ -80,6 +117,233 @@ static void mbedtls_zeroize( void *v, size_t n ) { static unsigned long add_count, dbl_count, mul_count; #endif +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Maximum number of "basic operations" to be done in a row. + * + * Default value 0 means that ECC operations will not yield. + * Note that regardless of the value of ecp_max_ops, always at + * least one step is performed before yielding. + * + * Setting ecp_max_ops=1 can be suitable for testing purposes + * as it will interrupt computation at all possible points. + */ +static unsigned ecp_max_ops = 0; + +/* + * Set ecp_max_ops + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ) +{ + ecp_max_ops = max_ops; +} + +/* + * Check if restart is enabled + */ +int mbedtls_ecp_restart_is_enabled( void ) +{ + return( ecp_max_ops != 0 ); +} + +/* + * Restart sub-context for ecp_mul_comb() + */ +struct mbedtls_ecp_restart_mul +{ + mbedtls_ecp_point R; /* current intermediate result */ + size_t i; /* current index in various loops, 0 outside */ + mbedtls_ecp_point *T; /* table for precomputed points */ + unsigned char T_size; /* number of points in table T */ + enum { /* what were we doing last time we returned? */ + ecp_rsm_init = 0, /* nothing so far, dummy initial state */ + ecp_rsm_pre_dbl, /* precompute 2^n multiples */ + ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ + ecp_rsm_pre_add, /* precompute remaining points by adding */ + ecp_rsm_pre_norm_add, /* normalize all precomputed points */ + ecp_rsm_comb_core, /* ecp_mul_comb_core() */ + ecp_rsm_final_norm, /* do the final normalization */ + } state; +}; + +/* + * Init restart_mul sub-context + */ +static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->R ); + ctx->i = 0; + ctx->T = NULL; + ctx->T_size = 0; + ctx->state = ecp_rsm_init; +} + +/* + * Free the components of a restart_mul sub-context + */ +static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + unsigned char i; + + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->R ); + + if( ctx->T != NULL ) + { + for( i = 0; i < ctx->T_size; i++ ) + mbedtls_ecp_point_free( ctx->T + i ); + mbedtls_free( ctx->T ); + } + + ecp_restart_rsm_init( ctx ); +} + +/* + * Restart context for ecp_muladd() + */ +struct mbedtls_ecp_restart_muladd +{ + mbedtls_ecp_point mP; /* mP value */ + mbedtls_ecp_point R; /* R intermediate result */ + enum { /* what should we do next? */ + ecp_rsma_mul1 = 0, /* first multiplication */ + ecp_rsma_mul2, /* second multiplication */ + ecp_rsma_add, /* addition */ + ecp_rsma_norm, /* normalization */ + } state; +}; + +/* + * Init restart_muladd sub-context + */ +static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->mP ); + mbedtls_ecp_point_init( &ctx->R ); + ctx->state = ecp_rsma_mul1; +} + +/* + * Free the components of a restart_muladd sub-context + */ +static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->mP ); + mbedtls_ecp_point_free( &ctx->R ); + + ecp_restart_ma_init( ctx ); +} + +/* + * Initialize a restart context + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +{ + ECP_VALIDATE( ctx != NULL ); + ctx->ops_done = 0; + ctx->depth = 0; + ctx->rsm = NULL; + ctx->ma = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_restart_rsm_free( ctx->rsm ); + mbedtls_free( ctx->rsm ); + + ecp_restart_ma_free( ctx->ma ); + mbedtls_free( ctx->ma ); + + mbedtls_ecp_restart_init( ctx ); +} + +/* + * Check if we can do the next step + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ) +{ + ECP_VALIDATE_RET( grp != NULL ); + + if( rs_ctx != NULL && ecp_max_ops != 0 ) + { + /* scale depending on curve size: the chosen reference is 256-bit, + * and multiplication is quadratic. Round to the closest integer. */ + if( grp->pbits >= 512 ) + ops *= 4; + else if( grp->pbits >= 384 ) + ops *= 2; + + /* Avoid infinite loops: always allow first step. + * Because of that, however, it's not generally true + * that ops_done <= ecp_max_ops, so the check + * ops_done > ecp_max_ops below is mandatory. */ + if( ( rs_ctx->ops_done != 0 ) && + ( rs_ctx->ops_done > ecp_max_ops || + ops > ecp_max_ops - rs_ctx->ops_done ) ) + { + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + } + + /* update running count */ + rs_ctx->ops_done += ops; + } + + return( 0 ); +} + +/* Call this when entering a function that needs its own sub-context */ +#define ECP_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ + rs_ctx->ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECP_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECP_RS_ENTER( sub ) (void) rs_ctx; +#define ECP_RS_LEAVE( sub ) (void) rs_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ @@ -94,7 +358,8 @@ static unsigned long add_count, dbl_count, mul_count; #define ECP_SHORTWEIERSTRASS #endif -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #define ECP_MONTGOMERY #endif @@ -240,6 +505,9 @@ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name { const mbedtls_ecp_curve_info *curve_info; + if( name == NULL ) + return( NULL ); + for( curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++ ) @@ -270,8 +538,7 @@ static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) */ void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) { - if( pt == NULL ) - return; + ECP_VALIDATE( pt != NULL ); mbedtls_mpi_init( &pt->X ); mbedtls_mpi_init( &pt->Y ); @@ -283,10 +550,23 @@ void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) */ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) { - if( grp == NULL ) - return; + ECP_VALIDATE( grp != NULL ); - memset( grp, 0, sizeof( mbedtls_ecp_group ) ); + grp->id = MBEDTLS_ECP_DP_NONE; + mbedtls_mpi_init( &grp->P ); + mbedtls_mpi_init( &grp->A ); + mbedtls_mpi_init( &grp->B ); + mbedtls_ecp_point_init( &grp->G ); + mbedtls_mpi_init( &grp->N ); + grp->pbits = 0; + grp->nbits = 0; + grp->h = 0; + grp->modp = NULL; + grp->t_pre = NULL; + grp->t_post = NULL; + grp->t_data = NULL; + grp->T = NULL; + grp->T_size = 0; } /* @@ -294,8 +574,7 @@ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) */ void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) { - if( key == NULL ) - return; + ECP_VALIDATE( key != NULL ); mbedtls_ecp_group_init( &key->grp ); mbedtls_mpi_init( &key->d ); @@ -341,7 +620,7 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) mbedtls_free( grp->T ); } - mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); + mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); } /* @@ -363,6 +642,8 @@ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) { int ret; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); @@ -377,7 +658,10 @@ cleanup: */ int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) { - return mbedtls_ecp_group_load( dst, src->id ); + ECP_VALIDATE_RET( dst != NULL ); + ECP_VALIDATE_RET( src != NULL ); + + return( mbedtls_ecp_group_load( dst, src->id ) ); } /* @@ -386,6 +670,7 @@ int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) { int ret; + ECP_VALIDATE_RET( pt != NULL ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); @@ -400,15 +685,20 @@ cleanup: */ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) { + ECP_VALIDATE_RET( pt != NULL ); + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); } /* - * Compare two points lazyly + * Compare two points lazily */ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) { + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) @@ -426,6 +716,9 @@ int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, const char *x, const char *y ) { int ret; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( x != NULL ); + ECP_VALIDATE_RET( y != NULL ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); @@ -438,16 +731,19 @@ cleanup: /* * Export a point into unsigned binary data (SEC1 2.3.3) */ -int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, - int format, size_t *olen, - unsigned char *buf, size_t buflen ) +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) { int ret = 0; size_t plen; - - if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && - format != MBEDTLS_ECP_PF_COMPRESSED ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); /* * Common case: P == 0 @@ -494,11 +790,15 @@ cleanup: /* * Import a point from unsigned binary data (SEC1 2.3.4) */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char *buf, size_t ilen ) +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) { int ret; size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); if( ilen < 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -533,11 +833,16 @@ cleanup: * opaque point <1..2^8-1>; * } ECPoint; */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t buf_len ) +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) { unsigned char data_len; const unsigned char *buf_start; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); /* * We must have at least two bytes (1 for length, at least one for data) @@ -555,7 +860,7 @@ int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point buf_start = *buf; *buf += data_len; - return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); + return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) ); } /* @@ -569,6 +874,12 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp unsigned char *buf, size_t blen ) { int ret; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); /* * buffer length must be at least one, for our length byte @@ -592,10 +903,33 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp /* * Set a group from an ECParameters record (RFC 4492) */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_group_load( grp, grp_id ) ); +} + +/* + * Read a group id from an ECParameters record (RFC 4492) and convert it to + * mbedtls_ecp_group_id. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, size_t len ) { uint16_t tls_id; const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); /* * We expect at least three bytes (see below) @@ -619,7 +953,9 @@ int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **bu if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - return mbedtls_ecp_group_load( grp, curve_info->grp_id ); + *grp = curve_info->grp_id; + + return( 0 ); } /* @@ -629,6 +965,9 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen ) { const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( olen != NULL ); if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -748,6 +1087,11 @@ static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) return( 0 ); +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac( grp, pt ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); /* @@ -787,25 +1131,33 @@ cleanup: * Cost: 1N(t) := 1I + (6t - 3)M + 1S */ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *T[], size_t t_len ) + mbedtls_ecp_point *T[], size_t T_size ) { int ret; size_t i; mbedtls_mpi *c, u, Zi, ZZi; - if( t_len < 2 ) + if( T_size < 2 ) return( ecp_normalize_jac( grp, *T ) ); - if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) ); +#endif + + if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_init( &c[i] ); + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); /* * c[i] = Z_0 * ... * Z_i */ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); - for( i = 1; i < t_len; i++ ) + for( i = 1; i < T_size; i++ ) { MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); MOD_MUL( c[i] ); @@ -814,9 +1166,9 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, /* * u = 1 / (Z_0 * ... * Z_n) mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) ); - for( i = t_len - 1; ; i-- ) + for( i = T_size - 1; ; i-- ) { /* * Zi = 1 / Z_i mod p @@ -856,7 +1208,7 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, cleanup: mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); - for( i = 0; i < t_len; i++ ) + for( i = 0; i < T_size; i++ ) mbedtls_mpi_free( &c[i] ); mbedtls_free( c ); @@ -912,6 +1264,11 @@ static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, dbl_count++; #endif +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_jac( grp, R, P ) ); +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); /* Special case for A = -3 */ @@ -1003,6 +1360,11 @@ static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, add_count++; #endif +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) ); +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + /* * Trivial cases: P == 0 or Q == 0 (case 1) */ @@ -1080,15 +1442,21 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p { int ret; mbedtls_mpi l, ll; - size_t p_size = ( grp->pbits + 7 ) / 8; + size_t p_size; int count = 0; +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); /* Generate l such that 1 < l < p */ do { - mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ); + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); @@ -1135,11 +1503,38 @@ cleanup: * modified version that provides resistance to SPA by avoiding zero * digits in the representation as in [3]. We modify the method further by * requiring that all K_i be odd, which has the small cost that our - * representation uses one more K_i, due to carries. + * representation uses one more K_i, due to carries, but saves on the size of + * the precomputed table. * - * Also, for the sake of compactness, only the seven low-order bits of x[i] - * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in - * the paper): it is set if and only if if s_i == -1; + * Summary of the comb method and its modifications: + * + * - The goal is to compute m*P for some w*d-bit integer m. + * + * - The basic comb method splits m into the w-bit integers + * x[0] .. x[d-1] where x[i] consists of the bits in m whose + * index has residue i modulo d, and computes m * P as + * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where + * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. + * + * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by + * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., + * thereby successively converting it into a form where all summands + * are nonzero, at the cost of negative summands. This is the basic idea of [3]. + * + * - More generally, even if x[i+1] != 0, we can first transform the sum as + * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., + * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. + * Performing and iterating this procedure for those x[i] that are even + * (keeping track of carry), we can transform the original sum into one of the form + * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] + * with all x'[i] odd. It is therefore only necessary to know S at odd indices, + * which is why we are only computing half of it in the first place in + * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. + * + * - For the sake of compactness, only the seven low-order bits of x[i] + * are used to represent its absolute value (K_i in the paper), and the msb + * of x[i] encodes the sign (s_i in the paper): it is set if and only if + * if s_i == -1; * * Calling conventions: * - x is an array of size d + 1 @@ -1148,8 +1543,8 @@ cleanup: * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d * (the result will be incorrect if these assumptions are not satisfied) */ -static void ecp_comb_fixed( unsigned char x[], size_t d, - unsigned char w, const mbedtls_mpi *m ) +static void ecp_comb_recode_core( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) { size_t i, j; unsigned char c, cc, adjust; @@ -1179,69 +1574,178 @@ static void ecp_comb_fixed( unsigned char x[], size_t d, } /* - * Precompute points for the comb method + * Precompute points for the adapted comb method * - * If i = i_{w-1} ... i_1 is the binary representation of i, then - * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P + * Assumption: T must be able to hold 2^{w - 1} elements. * - * T must be able to hold 2^{w - 1} elements + * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, + * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. * * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + * + * Note: Even comb values (those where P would be omitted from the + * sum defining T[i] above) are not needed in our adaption + * the comb method. See ecp_comb_recode_core(). + * + * This function currently works in four steps: + * (1) [dbl] Computation of intermediate T[i] for 2-power values of i + * (2) [norm_dbl] Normalization of coordinates of these T[i] + * (3) [add] Computation of all T[i] + * (4) [norm_add] Normalization of all T[i] + * + * Step 1 can be interrupted but not the others; together with the final + * coordinate normalization they are the largest steps done at once, depending + * on the window size. Here are operation counts for P-256: + * + * step (2) (3) (4) + * w = 5 142 165 208 + * w = 4 136 77 160 + * w = 3 130 33 136 + * w = 2 124 11 124 + * + * So if ECC operations are blocking for too long even with a low max_ops + * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order + * to minimize maximum blocking time. */ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point T[], const mbedtls_ecp_point *P, - unsigned char w, size_t d ) + unsigned char w, size_t d, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; - unsigned char i, k; - size_t j; + unsigned char i; + size_t j = 0; + const unsigned char T_size = 1U << ( w - 1 ); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + goto dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) + goto norm_dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_add ) + goto add; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) + goto norm_add; + } +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + rs_ctx->rsm->state = ecp_rsm_pre_dbl; + + /* initial state for the loop */ + rs_ctx->rsm->i = 0; + } + +dbl: +#endif /* * Set T[0] = P and * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) */ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); - k = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) - { - cur = T + i; - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); - for( j = 0; j < d; j++ ) - MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + j = rs_ctx->rsm->i; + else +#endif + j = 0; - TT[k++] = cur; + for( ; j < d * ( w - 1 ); j++ ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL ); + + i = 1U << ( j / d ); + cur = T + i; + + if( j % d == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); } - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; +norm_dbl: +#endif + /* + * Normalize current elements in T. As T has holes, + * use an auxiliary array of pointers to elements in T. + */ + j = 0; + for( i = 1; i < T_size; i <<= 1 ) + TT[j++] = T + i; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_add; + +add: +#endif /* * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ - k = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); + + for( i = 1; i < T_size; i <<= 1 ) { j = i; while( j-- ) - { MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); - TT[k++] = &T[i + j]; - } } - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_add; + +norm_add: +#endif + /* + * Normalize final elements in T. Even though there are no holes now, we + * still need the auxiliary array for homogeneity with the previous + * call. Also, skip T[0] which is already normalised, being a copy of P. + */ + for( j = 0; j + 1 < T_size; j++ ) + TT[j] = T + j + 1; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); cleanup: +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + rs_ctx->rsm->i = j; + } +#endif + return( ret ); } /* * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + * + * See ecp_comb_recode_core() for background */ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, + const mbedtls_ecp_point T[], unsigned char T_size, unsigned char i ) { int ret; @@ -1251,7 +1755,7 @@ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, ii = ( i & 0x7Fu ) >> 1; /* Read the whole table to thwart cache-based timing attacks */ - for( j = 0; j < t_len; j++ ) + for( j = 0; j < T_size; j++ ) { MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); @@ -1271,10 +1775,11 @@ cleanup: * Cost: d A + d D + 1 R */ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, + const mbedtls_ecp_point T[], unsigned char T_size, const unsigned char x[], size_t d, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; mbedtls_ecp_point Txi; @@ -1282,49 +1787,173 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R mbedtls_ecp_point_init( &Txi ); - /* Start with a non-zero point and randomize its coordinates */ - i = d; - MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); - if( f_rng != 0 ) - MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); +#if !defined(MBEDTLS_ECP_RESTARTABLE) + (void) rs_ctx; +#endif - while( i-- != 0 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + rs_ctx->rsm->state != ecp_rsm_comb_core ) { + rs_ctx->rsm->i = 0; + rs_ctx->rsm->state = ecp_rsm_comb_core; + } + + /* new 'if' instead of nested for the sake of the 'else' branch */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + { + /* restore current index (R already pointing to rs_ctx->rsm->R) */ + i = rs_ctx->rsm->i; + } + else +#endif + { + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + } + + while( i != 0 ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); + --i; + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); - MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); } cleanup: + mbedtls_ecp_point_free( &Txi ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + rs_ctx->rsm->i = i; + /* no need to save R, already pointing to rs_ctx->rsm->R */ + } +#endif + return( ret ); } /* - * Multiplication using the comb method, - * for curves in short Weierstrass form + * Recode the scalar to get constant-time comb multiplication + * + * As the actual scalar recoding needs an odd scalar as a starting point, + * this wrapper ensures that by replacing m by N - m if necessary, and + * informs the caller that the result of multiplication will be negated. + * + * This works because we only support large prime order for Short Weierstrass + * curves, so N is always odd hence either m or N - m is. + * + * See ecp_comb_recode_core() for background. */ -static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, + const mbedtls_mpi *m, + unsigned char k[COMB_MAX_D + 1], + size_t d, + unsigned char w, + unsigned char *parity_trick ) { int ret; - unsigned char w, m_is_odd, p_eq_g, pre_len, i; - size_t d; - unsigned char k[COMB_MAX_D + 1]; - mbedtls_ecp_point *T; mbedtls_mpi M, mm; mbedtls_mpi_init( &M ); mbedtls_mpi_init( &mm ); - /* we need N to be odd to trnaform m in an odd number, check now */ + /* N is always odd (see above), just make extra sure */ if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + /* do we need the parity trick? */ + *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 ); + + /* execute parity fix in constant time */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) ); + + /* actual scalar recoding */ + ecp_comb_recode_core( k, d, w, &M ); + +cleanup: + mbedtls_mpi_free( &mm ); + mbedtls_mpi_free( &M ); + + return( ret ); +} + +/* + * Perform comb multiplication (for short Weierstrass curves) + * once the auxiliary table has been pre-computed. + * + * Scalar recoding may use a parity trick that makes us compute -m * P, + * if that is the case we'll need to recover m * P at the end. + */ +static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *T, + unsigned char T_size, + unsigned char w, + size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + unsigned char parity_trick; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *RR = R; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + RR = &rs_ctx->rsm->R; + + if( rs_ctx->rsm->state == ecp_rsm_final_norm ) + goto final_norm; + } +#endif + + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, + &parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, + f_rng, p_rng, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_final_norm; + +final_norm: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); +#endif + +cleanup: + return( ret ); +} + +/* + * Pick window size based on curve size and whether we optimize for base point + */ +static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, + unsigned char p_eq_g ) +{ + unsigned char w; + /* * Minimize the number of multiplications, that is minimize * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) @@ -1337,14 +1966,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * Just adding one avoids upping the cost of the first mul too much, * and the memory cost too. */ -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 - p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && - mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); if( p_eq_g ) w++; -#else - p_eq_g = 0; -#endif /* * Make sure w is within bounds. @@ -1355,70 +1978,140 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, if( w >= grp->nbits ) w = 2; - /* Other sizes that depend on w */ - pre_len = 1U << ( w - 1 ); + return( w ); +} + +/* + * Multiplication using the comb method - for curves in short Weierstrass form + * + * This function is mainly responsible for administrative work: + * - managing the restart context if enabled + * - managing the table of precomputed points (passed between the below two + * functions): allocation, computation, ownership tranfer, freeing. + * + * It delegates the actual arithmetic work to: + * ecp_precompute_comb() and ecp_mul_comb_with_precomp() + * + * See comments on ecp_comb_recode_core() regarding the computation strategy. + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + unsigned char w, p_eq_g, i; + size_t d; + unsigned char T_size, T_ok; + mbedtls_ecp_point *T; + + ECP_RS_ENTER( rsm ); + + /* Is P the base point ? */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); +#else + p_eq_g = 0; +#endif + + /* Pick window size and deduce related sizes */ + w = ecp_pick_window_size( grp, p_eq_g ); + T_size = 1U << ( w - 1 ); d = ( grp->nbits + w - 1 ) / w; - /* - * Prepare precomputed points: if P == G we want to - * use grp->T if already initialized, or initialize it. - */ - T = p_eq_g ? grp->T : NULL; - - if( T == NULL ) + /* Pre-computed table: do we have it already for the base point? */ + if( p_eq_g && grp->T != NULL ) { - T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); + /* second pointer to the same table, will be deleted on exit */ + T = grp->T; + T_ok = 1; + } + else +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* Pre-computed table: do we have one in progress? complete? */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL ) + { + /* transfer ownership of T from rsm to local function */ + T = rs_ctx->rsm->T; + rs_ctx->rsm->T = NULL; + rs_ctx->rsm->T_size = 0; + + /* This effectively jumps to the call to mul_comb_after_precomp() */ + T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; + } + else +#endif + /* Allocate table if we didn't have any */ + { + T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); if( T == NULL ) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } - MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_init( &T[i] ); + + T_ok = 0; + } + + /* Compute table (or finish computing it) if not done already */ + if( !T_ok ) + { + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) ); if( p_eq_g ) { + /* almost transfer ownership of T to the group, but keep a copy of + * the pointer to use for calling the next function more easily */ grp->T = T; - grp->T_size = pre_len; + grp->T_size = T_size; } } - /* - * Make sure M is odd (M = m or M = N - m, since N is odd) - * using the fact that m * P = - (N - m) * P - */ - m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); - - /* - * Go for comb multiplication, R = M * P - */ - ecp_comb_fixed( k, d, w, &M ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); - - /* - * Now get m * P from M * P and normalize it - */ - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + /* Actual comb multiplication using precomputed points */ + MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, + T, T_size, w, d, + f_rng, p_rng, rs_ctx ) ); cleanup: - if( T != NULL && ! p_eq_g ) + /* does T belong to the group? */ + if( T == grp->T ) + T = NULL; + + /* does T belong to the restart context? */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) { - for( i = 0; i < pre_len; i++ ) + /* transfer ownership of T from local function to rsm */ + rs_ctx->rsm->T_size = T_size; + rs_ctx->rsm->T = T; + T = NULL; + } +#endif + + /* did T belong to us? then let's destroy it! */ + if( T != NULL ) + { + for( i = 0; i < T_size; i++ ) mbedtls_ecp_point_free( &T[i] ); mbedtls_free( T ); } - mbedtls_mpi_free( &M ); - mbedtls_mpi_free( &mm ); - + /* don't free R while in progress in case R == P */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + /* prevent caller from using invalid value */ if( ret != 0 ) mbedtls_ecp_point_free( R ); + ECP_RS_LEAVE( rsm ); + return( ret ); } @@ -1441,6 +2134,11 @@ static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P { int ret; +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_mxz( grp, P ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); @@ -1462,15 +2160,21 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P { int ret; mbedtls_mpi l; - size_t p_size = ( grp->pbits + 7 ) / 8; + size_t p_size; int count = 0; +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; mbedtls_mpi_init( &l ); /* Generate l such that 1 < l < p */ do { - mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ); + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); @@ -1512,6 +2216,11 @@ static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, int ret; mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) ); +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); @@ -1605,6 +2314,72 @@ cleanup: #endif /* ECP_MONTGOMERY */ +/* + * Restartable multiplication R = m * P + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) + rs_ctx->ops_done = 0; +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* skip argument check when restarting */ + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + { + /* check_privkey is free */ + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK ); + + /* Common sanity checks */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); + } + + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); +#endif + +cleanup: + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL ) + rs_ctx->depth--; +#endif + + return( ret ); +} + /* * Multiplication R = m * P */ @@ -1612,25 +2387,11 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret; - - /* Common sanity checks */ - if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || - ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) - return( ret ); - -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - return( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); -#endif -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng ) ); -#endif - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) ); } #if defined(ECP_SHORTWEIERSTRASS) @@ -1690,7 +2451,8 @@ cleanup: static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, - const mbedtls_ecp_point *P ) + const mbedtls_ecp_point *P, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; @@ -1706,13 +2468,111 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, } else { - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P, + NULL, NULL, rs_ctx ) ); } cleanup: return( ret ); } +/* + * Restartable linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_ecp_point mP; + mbedtls_ecp_point *pmP = &mP; + mbedtls_ecp_point *pR = R; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + ECP_RS_ENTER( ma ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + { + /* redirect intermediate results to restart context */ + pmP = &rs_ctx->ma->mP; + pR = &rs_ctx->ma->R; + + /* jump to next operation */ + if( rs_ctx->ma->state == ecp_rsma_mul2 ) + goto mul2; + if( rs_ctx->ma->state == ecp_rsma_add ) + goto add; + if( rs_ctx->ma->state == ecp_rsma_norm ) + goto norm; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_mul2; + +mul2: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_add; + +add: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_norm; + +norm: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); +#endif + +cleanup: +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + + mbedtls_ecp_point_free( &mP ); + + ECP_RS_LEAVE( ma ); + + return( ret ); +} + /* * Linear combination * NOT constant-time @@ -1721,27 +2581,15 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) { - int ret; - mbedtls_ecp_point mP; - - if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - - mbedtls_ecp_point_init( &mP ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); - - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); - -cleanup: - mbedtls_ecp_point_free( &mP ); - - return( ret ); + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) ); } - #if defined(ECP_MONTGOMERY) /* * Check validity of a public key for Montgomery curves with x-only schemes @@ -1749,6 +2597,8 @@ cleanup: static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) { /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + /* Allow any public value, if it's too big then we'll just reduce it mod p + * (RFC 7748 sec. 5 para. 3). */ if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) return( MBEDTLS_ERR_ECP_INVALID_KEY ); @@ -1759,8 +2609,12 @@ static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_ /* * Check that a point is valid as a public key */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ) { + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + /* Must use affine coordinates */ if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) return( MBEDTLS_ERR_ECP_INVALID_KEY ); @@ -1779,19 +2633,26 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po /* * Check that an mbedtls_mpi is valid as a private key */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ) { + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) { - /* see [Curve25519] page 5 */ + /* see RFC 7748 sec. 5 para. 5 */ if( mbedtls_mpi_get_bit( d, 0 ) != 0 || mbedtls_mpi_get_bit( d, 1 ) != 0 || - mbedtls_mpi_get_bit( d, 2 ) != 0 || mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ return( MBEDTLS_ERR_ECP_INVALID_KEY ); - else - return( 0 ); + + /* see [Curve25519] page 5 */ + if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); } #endif /* ECP_MONTGOMERY */ #if defined(ECP_SHORTWEIERSTRASS) @@ -1810,16 +2671,21 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi * } /* - * Generate a keypair with configurable base point + * Generate a private key */ -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret; - size_t n_size = ( grp->nbits + 7 ) / 8; + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + size_t n_size; + + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + n_size = ( grp->nbits + 7 ) / 8; #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) @@ -1838,19 +2704,22 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, else MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); - /* Make sure the last three bits are unset */ + /* Make sure the last two bits are unset for Curve448, three bits for + Curve25519 */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + if( grp->nbits == 254 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } } - else #endif /* ECP_MONTGOMERY */ + #if defined(ECP_SHORTWEIERSTRASS) if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) { /* SEC1 3.2.1: Generate d such that 1 <= n < N */ int count = 0; - unsigned char rnd[MBEDTLS_ECP_MAX_BYTES]; /* * Match the procedure given in RFC 6979 (deterministic ECDSA): @@ -1861,8 +2730,7 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, */ do { - MBEDTLS_MPI_CHK( f_rng( p_rng, rnd, n_size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); /* @@ -1880,15 +2748,33 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); } - else #endif /* ECP_SHORTWEIERSTRASS */ - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); cleanup: - if( ret != 0 ) - return( ret ); + return( ret ); +} - return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( G != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); + +cleanup: + return( ret ); } /* @@ -1899,6 +2785,11 @@ int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); } @@ -1909,6 +2800,8 @@ int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) return( ret ); @@ -1924,6 +2817,8 @@ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ec int ret; mbedtls_ecp_point Q; mbedtls_ecp_group grp; + ECP_VALIDATE_RET( pub != NULL ); + ECP_VALIDATE_RET( prv != NULL ); if( pub->grp.id == MBEDTLS_ECP_DP_NONE || pub->grp.id != prv->grp.id || @@ -2089,4 +2984,6 @@ cleanup: #endif /* MBEDTLS_SELF_TEST */ +#endif /* !MBEDTLS_ECP_ALT */ + #endif /* MBEDTLS_ECP_C */ diff --git a/Externals/mbedtls/library/ecp_curves.c b/Externals/mbedtls/library/ecp_curves.c index 9a6e8eb187..731621dc3c 100644 --- a/Externals/mbedtls/library/ecp_curves.c +++ b/Externals/mbedtls/library/ecp_curves.c @@ -28,9 +28,18 @@ #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" #include +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline @@ -625,6 +634,9 @@ static int ecp_mod_p521( mbedtls_mpi * ); #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) static int ecp_mod_p255( mbedtls_mpi * ); #endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +static int ecp_mod_p448( mbedtls_mpi * ); +#endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static int ecp_mod_p192k1( mbedtls_mpi * ); #endif @@ -668,7 +680,12 @@ static int ecp_use_curve25519( mbedtls_ecp_group *grp ) MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - /* Y intentionaly not set, since we use x/z coordinates. + /* N = 2^252 + 27742317777372353535851937790883648493 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->N, 16, + "14DEF9DEA2F79CD65812631A5CF5D3ED" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) ); + + /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); @@ -685,11 +702,58 @@ cleanup: } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448( mbedtls_ecp_group *grp ) +{ + mbedtls_mpi Ns; + int ret; + + mbedtls_mpi_init( &Ns ); + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "98AA" ) ); + + /* P = 2^448 - 2^224 - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Ns, 16, + "8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) ); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + mbedtls_mpi_free( &Ns ); + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + /* * Set a group using well-known domain parameters */ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) { + ECP_VALIDATE_RET( grp != NULL ); mbedtls_ecp_group_free( grp ); grp->id = id; @@ -765,6 +829,12 @@ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) return( ecp_use_curve25519( grp ) ); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + grp->modp = ecp_mod_p448; + return( ecp_use_curve448( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + default: mbedtls_ecp_group_free( grp ); return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); @@ -1174,7 +1244,7 @@ static int ecp_mod_p255( mbedtls_mpi *N ) M.s = 1; M.n = N->n - ( P255_WIDTH - 1 ); if( M.n > P255_WIDTH + 1 ) - M.n = P255_WIDTH + 1; + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); M.p = Mp; memset( Mp, 0, sizeof Mp ); memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); @@ -1195,6 +1265,77 @@ cleanup: } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/* Size of p448 in terms of mbedtls_mpi_uint */ +#define P448_WIDTH ( 448 / 8 / sizeof( mbedtls_mpi_uint ) ) + +/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ +#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) ) +#define P224_WIDTH_MIN ( 28 / sizeof( mbedtls_mpi_uint ) ) +#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) ) +#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 ) + +/* + * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return + * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference + * implementation of Curve448, which uses its own special 56-bit limbs rather + * than a generic bignum library. We could squeeze some extra speed out on + * 32-bit machines by splitting N up into 32-bit limbs and doing the + * arithmetic using the limbs directly as we do for the NIST primes above, + * but for 64-bit targets it should use half the number of operations if we do + * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. + */ +static int ecp_mod_p448( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M, Q; + mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; + + if( N->n <= P448_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P448_WIDTH ); + if( M.n > P448_WIDTH ) + /* Shouldn't be called with N larger than 2^896! */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof( Mp ) ); + memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) ); + + /* N = A0 */ + for( i = P448_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N += A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + + /* Q = B1, N += B1 */ + Q = M; + Q.p = Qp; + memcpy( Qp, Mp, sizeof( Qp ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) ); + + /* M = (B0 + B1) * 2^224, N += M */ + if( sizeof( mbedtls_mpi_uint ) > 4 ) + Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS ); + for( i = P224_WIDTH_MAX; i < M.n; ++i ) + Mp[i] = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) ); + M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) @@ -1213,7 +1354,7 @@ static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t int ret; size_t i; mbedtls_mpi M, R; - mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R]; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; if( N->n < p_limbs ) return( 0 ); @@ -1235,7 +1376,7 @@ static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); if( shift != 0 ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); - M.n += R.n - adjust; /* Make room for multiplication by R */ + M.n += R.n; /* Make room for multiplication by R */ /* N = A0 */ if( mask != 0 ) @@ -1257,7 +1398,7 @@ static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); if( shift != 0 ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); - M.n += R.n - adjust; /* Make room for multiplication by R */ + M.n += R.n; /* Make room for multiplication by R */ /* N = A0 */ if( mask != 0 ) @@ -1322,4 +1463,6 @@ static int ecp_mod_p256k1( mbedtls_mpi *N ) } #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#endif /* !MBEDTLS_ECP_ALT */ + #endif /* MBEDTLS_ECP_C */ diff --git a/Externals/mbedtls/library/entropy.c b/Externals/mbedtls/library/entropy.c index d4d1b27b7f..f8db1a5503 100644 --- a/Externals/mbedtls/library/entropy.c +++ b/Externals/mbedtls/library/entropy.c @@ -35,6 +35,7 @@ #include "mbedtls/entropy.h" #include "mbedtls/entropy_poll.h" +#include "mbedtls/platform_util.h" #include @@ -59,30 +60,30 @@ #include "mbedtls/havege.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) { - memset( ctx, 0, sizeof(mbedtls_entropy_context) ); + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init( &ctx->mutex ); #endif + ctx->accumulator_started = 0; #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_starts( &ctx->accumulator, 0 ); + mbedtls_sha512_init( &ctx->accumulator ); #else - mbedtls_sha256_starts( &ctx->accumulator, 0 ); + mbedtls_sha256_init( &ctx->accumulator ); #endif #if defined(MBEDTLS_HAVEGE_C) mbedtls_havege_init( &ctx->havege_data ); #endif + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + #if defined(MBEDTLS_TEST_NULL_ENTROPY) mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); @@ -113,6 +114,7 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, MBEDTLS_ENTROPY_BLOCK_SIZE, MBEDTLS_ENTROPY_SOURCE_STRONG ); + ctx->initial_entropy_run = 0; #endif #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ } @@ -125,31 +127,41 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free( &ctx->mutex ); #endif - mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_free( &ctx->accumulator ); +#else + mbedtls_sha256_free( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + ctx->initial_entropy_run = 0; +#endif + ctx->source_count = 0; + mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); + ctx->accumulator_started = 0; } int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, mbedtls_entropy_f_source_ptr f_source, void *p_source, size_t threshold, int strong ) { - int index, ret = 0; + int idx, ret = 0; #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif - index = ctx->source_count; - if( index >= MBEDTLS_ENTROPY_MAX_SOURCES ) + idx = ctx->source_count; + if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) { ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; goto exit; } - ctx->source[index].f_source = f_source; - ctx->source[index].p_source = p_source; - ctx->source[index].threshold = threshold; - ctx->source[index].strong = strong; + ctx->source[idx].f_source = f_source; + ctx->source[idx].p_source = p_source; + ctx->source[idx].threshold = threshold; + ctx->source[idx].strong = strong; ctx->source_count++; @@ -172,13 +184,16 @@ static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; size_t use_len = len; const unsigned char *p = data; + int ret = 0; if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) { #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512( data, len, tmp, 0 ); + if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; #else - mbedtls_sha256( data, len, tmp, 0 ); + if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; #endif p = tmp; use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; @@ -187,15 +202,35 @@ static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id header[0] = source_id; header[1] = use_len & 0xFF; + /* + * Start the accumulator if this has not already happened. Note that + * it is sufficient to start the accumulator here only because all calls to + * gather entropy eventually execute this code. + */ #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_update( &ctx->accumulator, header, 2 ); - mbedtls_sha512_update( &ctx->accumulator, p, use_len ); + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); #else - mbedtls_sha256_update( &ctx->accumulator, header, 2 ); - mbedtls_sha256_update( &ctx->accumulator, p, use_len ); + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); #endif - return( 0 ); +cleanup: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + return( ret ); } int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, @@ -242,7 +277,7 @@ static int entropy_gather_internal( mbedtls_entropy_context *ctx ) if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) { - return( ret ); + goto cleanup; } /* @@ -250,15 +285,20 @@ static int entropy_gather_internal( mbedtls_entropy_context *ctx ) */ if( olen > 0 ) { - entropy_update( ctx, (unsigned char) i, buf, olen ); + if( ( ret = entropy_update( ctx, (unsigned char) i, + buf, olen ) ) != 0 ) + return( ret ); ctx->source[i].size += olen; } } if( have_one_strong == 0 ) - return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ); + ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; - return( 0 ); +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); } /* @@ -333,33 +373,52 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_finish( &ctx->accumulator, buf ); + /* + * Note that at this stage it is assumed that the accumulator was started + * in a previous call to entropy_update(). If this is not guaranteed, the + * code below will fail. + */ + if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; /* * Reset accumulator and counters and recycle existing entropy */ - memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); - mbedtls_sha512_starts( &ctx->accumulator, 0 ); - mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + mbedtls_sha512_free( &ctx->accumulator ); + mbedtls_sha512_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; /* * Perform second SHA-512 on entropy */ - mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); + if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ - mbedtls_sha256_finish( &ctx->accumulator, buf ); + if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; /* * Reset accumulator and counters and recycle existing entropy */ - memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); - mbedtls_sha256_starts( &ctx->accumulator, 0 ); - mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + mbedtls_sha256_free( &ctx->accumulator ); + mbedtls_sha256_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; /* * Perform second SHA-256 on entropy */ - mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); + if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ for( i = 0; i < ctx->source_count; i++ ) @@ -370,6 +429,8 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) ret = 0; exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + #if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); @@ -382,7 +443,7 @@ exit: int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) { int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; - unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; /* Read new seed and write it to NV */ if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) @@ -393,9 +454,9 @@ int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) /* Manually update the remaining stream with a separator value to diverge */ memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); - mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); - return( 0 ); + return( ret ); } #endif /* MBEDTLS_ENTROPY_NV_SEED */ @@ -421,12 +482,15 @@ int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *p ret = 0; exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); return( ret ); } int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) { + int ret = 0; FILE *f; size_t n; unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; @@ -442,14 +506,16 @@ int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char * n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - } + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = mbedtls_entropy_update_manual( ctx, buf, n ); fclose( f ); - mbedtls_entropy_update_manual( ctx, buf, n ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); return( mbedtls_entropy_write_seed_file( ctx, path ) ); } diff --git a/Externals/mbedtls/library/entropy_poll.c b/Externals/mbedtls/library/entropy_poll.c index a116e605d2..4556f88a55 100644 --- a/Externals/mbedtls/library/entropy_poll.c +++ b/Externals/mbedtls/library/entropy_poll.c @@ -19,19 +19,25 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +#if defined(__linux__) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif +#include + #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #include "mbedtls/entropy_poll.h" #if defined(MBEDTLS_TIMING_C) -#include #include "mbedtls/timing.h" #endif #if defined(MBEDTLS_HAVEGE_C) @@ -44,7 +50,8 @@ #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" #endif @@ -92,6 +99,7 @@ int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len #include #if defined(SYS_getrandom) #define HAVE_GETRANDOM +#include static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) { @@ -101,47 +109,8 @@ static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) memset( buf, 0, buflen ); #endif #endif - return( syscall( SYS_getrandom, buf, buflen, flags ) ); } - -#include -/* Check if version is at least 3.17.0 */ -static int check_version_3_17_plus( void ) -{ - int minor; - struct utsname un; - const char *ver; - - /* Get version information */ - uname(&un); - ver = un.release; - - /* Check major version; assume a single digit */ - if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) - return( -1 ); - - if( ver[0] - '0' > 3 ) - return( 0 ); - - /* Ok, so now we know major == 3, check minor. - * Assume 1 or 2 digits. */ - if( ver[2] < '0' || ver[2] > '9' ) - return( -1 ); - - minor = ver[2] - '0'; - - if( ver[3] >= '0' && ver[3] <= '9' ) - minor = 10 * minor + ver[3] - '0'; - else if( ver [3] != '.' ) - return( -1 ); - - if( minor < 17 ) - return( -1 ); - - return( 0 ); -} -static int has_getrandom = -1; #endif /* SYS_getrandom */ #endif /* __linux__ */ @@ -152,22 +121,21 @@ int mbedtls_platform_entropy_poll( void *data, { FILE *file; size_t read_len; + int ret; ((void) data); #if defined(HAVE_GETRANDOM) - if( has_getrandom == -1 ) - has_getrandom = ( check_version_3_17_plus() == 0 ); - - if( has_getrandom ) + ret = getrandom_wrapper( output, len, 0 ); + if( ret >= 0 ) { - int ret; - - if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - *olen = ret; return( 0 ); } + else if( errno != ENOSYS ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + /* Fall through if the system call isn't known. */ +#else + ((void) ret); #endif /* HAVE_GETRANDOM */ *olen = 0; diff --git a/Externals/mbedtls/library/error.c b/Externals/mbedtls/library/error.c index dd2db0c45c..12312a0562 100644 --- a/Externals/mbedtls/library/error.c +++ b/Externals/mbedtls/library/error.c @@ -45,6 +45,14 @@ #include "mbedtls/aes.h" #endif +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + #if defined(MBEDTLS_BASE64_C) #include "mbedtls/base64.h" #endif @@ -65,10 +73,22 @@ #include "mbedtls/ccm.h" #endif +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #endif @@ -93,6 +113,10 @@ #include "mbedtls/gcm.h" #endif +#if defined(MBEDTLS_HKDF_C) +#include "mbedtls/hkdf.h" +#endif + #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #endif @@ -101,6 +125,18 @@ #include "mbedtls/md.h" #endif +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + #if defined(MBEDTLS_NET_C) #include "mbedtls/net_sockets.h" #endif @@ -129,10 +165,34 @@ #include "mbedtls/pkcs5.h" #endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/ssl.h" #endif @@ -174,7 +234,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); + mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters" ); if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) @@ -184,12 +244,14 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) - mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid, eg because it was free()ed" ); + mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid. For example, because it was freed" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Cipher hardware accelerator failed" ); #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_DHM_C) if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters to function" ); + mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters" ); if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) @@ -205,7 +267,11 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "DHM - Read/write of file failed" ); + mbedtls_snprintf( buf, buflen, "DHM - Read or write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - DHM hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Setting the modulus and generator failed" ); #endif /* MBEDTLS_DHM_C */ #if defined(MBEDTLS_ECP_C) @@ -214,17 +280,21 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "ECP - Requested curve not available" ); + mbedtls_snprintf( buf, buflen, "ECP - The requested feature is not available, for example, the requested curve is not supported" ); if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); + mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as ephemeral key, failed" ); if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); + mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" ); + if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" ); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_MD_C) @@ -236,6 +306,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); + if( use_ret == -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - MD hardware accelerator failed" ); #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) @@ -287,7 +359,9 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); + mbedtls_snprintf( buf, buflen, "PK - The buffer contains a valid signature followed by more data" ); + if( use_ret == -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - PK hardware accelerator failed" ); #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_PKCS12_C) @@ -320,7 +394,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the library's validity check" ); + mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the validity check of the library" ); if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) @@ -331,6 +405,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); + if( use_ret == -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION) ) + mbedtls_snprintf( buf, buflen, "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); + if( use_ret == -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - RSA hardware accelerator failed" ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SSL_TLS_C) @@ -426,7 +504,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) - mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" ); + mbedtls_snprintf( buf, buflen, "SSL - No data of requested type currently available on underlying transport" ); if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) @@ -439,6 +517,14 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" ); + if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) @@ -480,6 +566,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); + if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed" ); #endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ // END generated code @@ -516,8 +604,30 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_AES_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid input data" ); + if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" ); + if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "AES - AES hardware accelerator failed" ); #endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_ARC4_C) + if( use_ret == -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_ARIA_C) + if( use_ret == -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "ARIA - Bad input data" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ARIA - Feature not available. For example, an unsupported ARIA key size" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARIA - ARIA hardware accelerator failed" ); +#endif /* MBEDTLS_ARIA_C */ + #if defined(MBEDTLS_ASN1_PARSE_C) if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); @@ -562,40 +672,69 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) #endif /* MBEDTLS_BIGNUM_C */ #if defined(MBEDTLS_BLOWFISH_C) - if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Bad input data" ); if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" ); #endif /* MBEDTLS_BLOWFISH_C */ #if defined(MBEDTLS_CAMELLIA_C) - if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Bad input data" ); if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Camellia hardware accelerator failed" ); #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_CCM_C) if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) - mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to function" ); + mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to the function" ); if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" ); #endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHA20_C) + if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" ); +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" ); + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CMAC_C) + if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" ); +#endif /* MBEDTLS_CMAC_C */ + #if defined(MBEDTLS_CTR_DRBG_C) if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" ); + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The requested random buffer length is too big" ); if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The input (entropy + additional data) is too large" ); if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" ); + mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read or write error in file" ); #endif /* MBEDTLS_CTR_DRBG_C */ #if defined(MBEDTLS_DES_C) if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); + if( use_ret == -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DES - DES hardware accelerator failed" ); #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_ENTROPY_C) @@ -614,10 +753,17 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) #if defined(MBEDTLS_GCM_C) if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - GCM hardware accelerator failed" ); if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); #endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_HKDF_C) + if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" ); +#endif /* MBEDTLS_HKDF_C */ + #if defined(MBEDTLS_HMAC_DRBG_C) if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); @@ -629,6 +775,21 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); #endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_MD2_C) + if( use_ret == -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD2 - MD2 hardware accelerator failed" ); +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + if( use_ret == -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD4 - MD4 hardware accelerator failed" ); +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + if( use_ret == -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD5 - MD5 hardware accelerator failed" ); +#endif /* MBEDTLS_MD5_C */ + #if defined(MBEDTLS_NET_C) if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); @@ -652,6 +813,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); + if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "NET - Input invalid" ); #endif /* MBEDTLS_NET_C */ #if defined(MBEDTLS_OID_C) @@ -666,6 +831,48 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); #endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_PLATFORM_C) + if( use_ret == -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "PLATFORM - Hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED) ) + mbedtls_snprintf( buf, buflen, "PLATFORM - The requested feature is not supported by the platform" ); +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_POLY1305_C) + if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" ); +#endif /* MBEDTLS_POLY1305_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 input data was malformed" ); +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 input data was malformed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 input data was malformed" ); +#endif /* MBEDTLS_SHA512_C */ + #if defined(MBEDTLS_THREADING_C) if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); @@ -678,6 +885,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) #if defined(MBEDTLS_XTEA_C) if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); + if( use_ret == -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "XTEA - XTEA hardware accelerator failed" ); #endif /* MBEDTLS_XTEA_C */ // END generated code diff --git a/Externals/mbedtls/library/gcm.c b/Externals/mbedtls/library/gcm.c index f1210c52c3..675926a518 100644 --- a/Externals/mbedtls/library/gcm.c +++ b/Externals/mbedtls/library/gcm.c @@ -38,6 +38,7 @@ #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" +#include "mbedtls/platform_util.h" #include @@ -46,14 +47,22 @@ #endif #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/aes.h" #include "mbedtls/platform.h" -#else +#if !defined(MBEDTLS_PLATFORM_C) #include #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ +#if !defined(MBEDTLS_GCM_ALT) + +/* Parameter validation macros */ +#define GCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT ) +#define GCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + /* * 32-bit integer manipulation macros (big endian) */ @@ -77,16 +86,12 @@ } #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Initialize a context */ void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) { + GCM_VALIDATE( ctx != NULL ); memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); } @@ -166,6 +171,10 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, int ret; const mbedtls_cipher_info_t *cipher_info; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( key != NULL ); + GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 ); + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); if( cipher_info == NULL ) return( MBEDTLS_ERR_GCM_BAD_INPUT ); @@ -276,9 +285,15 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, const unsigned char *p; size_t use_len, olen = 0; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ - if( ( (uint64_t) iv_len ) >> 61 != 0 || - ( (uint64_t) add_len ) >> 61 != 0 ) + /* IV is not allowed to be zero length */ + if( iv_len == 0 || + ( (uint64_t) iv_len ) >> 61 != 0 || + ( (uint64_t) add_len ) >> 61 != 0 ) { return( MBEDTLS_ERR_GCM_BAD_INPUT ); } @@ -356,6 +371,10 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx, unsigned char *out_p = output; size_t use_len, olen = 0; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + if( output > input && (size_t) ( output - input ) < length ) return( MBEDTLS_ERR_GCM_BAD_INPUT ); @@ -409,8 +428,14 @@ int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, { unsigned char work_buf[16]; size_t i; - uint64_t orig_len = ctx->len * 8; - uint64_t orig_add_len = ctx->add_len * 8; + uint64_t orig_len; + uint64_t orig_add_len; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + orig_len = ctx->len * 8; + orig_add_len = ctx->add_len * 8; if( tag_len > 16 || tag_len < 4 ) return( MBEDTLS_ERR_GCM_BAD_INPUT ); @@ -452,6 +477,13 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, { int ret; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) return( ret ); @@ -480,6 +512,13 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, size_t i; int diff; + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag ) ) != 0 ) @@ -493,7 +532,7 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, if( diff != 0 ) { - mbedtls_zeroize( output, length ); + mbedtls_platform_zeroize( output, length ); return( MBEDTLS_ERR_GCM_AUTH_FAILED ); } @@ -502,10 +541,14 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) { + if( ctx == NULL ) + return; mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); } +#endif /* !MBEDTLS_GCM_ALT */ + #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /* * AES-GCM test vectors from: @@ -742,34 +785,48 @@ int mbedtls_gcm_self_test( int verbose ) int i, j, ret; mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; - mbedtls_gcm_init( &ctx ); - for( j = 0; j < 3; j++ ) { int key_len = 128 + 64 * j; for( i = 0; i < MAX_TESTS; i++ ) { + mbedtls_gcm_init( &ctx ); + if( verbose != 0 ) mbedtls_printf( " AES-GCM-%3d #%d (%s): ", - key_len, i, "enc" ); + key_len, i, "enc" ); - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 ) + { + mbedtls_printf( "skipped\n" ); + break; + } + else if( ret != 0 ) + { + goto exit; + } ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, - pt_len[i], - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i], - pt[pt_index[i]], buf, 16, tag_buf ); + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + pt[pt_index[i]], buf, 16, tag_buf ); + if( ret != 0 ) + goto exit; - if( ret != 0 || - memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) + if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); + ret = 1; + goto exit; } mbedtls_gcm_free( &ctx ); @@ -777,26 +834,31 @@ int mbedtls_gcm_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n" ); + mbedtls_gcm_init( &ctx ); + if( verbose != 0 ) mbedtls_printf( " AES-GCM-%3d #%d (%s): ", - key_len, i, "dec" ); + key_len, i, "dec" ); - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, - pt_len[i], - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i], - ct[j * 6 + i], buf, 16, tag_buf ); + pt_len[i], + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i], + ct[j * 6 + i], buf, 16, tag_buf ); - if( ret != 0 || - memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); + ret = 1; + goto exit; } mbedtls_gcm_free( &ctx ); @@ -804,66 +866,51 @@ int mbedtls_gcm_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n" ); + mbedtls_gcm_init( &ctx ); + if( verbose != 0 ) mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", - key_len, i, "enc" ); + key_len, i, "enc" ); - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i] ); + iv[iv_index[i]], iv_len[i], + additional[add_index[i]], add_len[i] ); if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + goto exit; if( pt_len[i] > 32 ) { size_t rest_len = pt_len[i] - 32; ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + goto exit; ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, buf + 32 ); if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + goto exit; } else { ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + goto exit; } ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); - if( ret != 0 || - memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || + if( ret != 0 ) + goto exit; + + if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); + ret = 1; + goto exit; } mbedtls_gcm_free( &ctx ); @@ -871,80 +918,75 @@ int mbedtls_gcm_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n" ); + mbedtls_gcm_init( &ctx ); + if( verbose != 0 ) mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", - key_len, i, "dec" ); + key_len, i, "dec" ); - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); + ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], + key_len ); + if( ret != 0 ) + goto exit; ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, iv[iv_index[i]], iv_len[i], additional[add_index[i]], add_len[i] ); if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + goto exit; if( pt_len[i] > 32 ) { size_t rest_len = pt_len[i] - 32; ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + goto exit; ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, - buf + 32 ); + buf + 32 ); if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + goto exit; } else { - ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); + ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], + buf ); if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + goto exit; } ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); - if( ret != 0 || - memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); + ret = 1; + goto exit; } mbedtls_gcm_free( &ctx ); if( verbose != 0 ) mbedtls_printf( "passed\n" ); - } } if( verbose != 0 ) mbedtls_printf( "\n" ); - return( 0 ); + ret = 0; + +exit: + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + mbedtls_gcm_free( &ctx ); + } + + return( ret ); } #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ diff --git a/Externals/mbedtls/library/havege.c b/Externals/mbedtls/library/havege.c index 2b75ef7bd8..4dcac02875 100644 --- a/Externals/mbedtls/library/havege.c +++ b/Externals/mbedtls/library/havege.c @@ -36,14 +36,10 @@ #include "mbedtls/havege.h" #include "mbedtls/timing.h" +#include "mbedtls/platform_util.h" #include -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* ------------------------------------------------------------------------ * On average, one iteration accesses two 8-word blocks in the havege WALK * table, and generates 16 words in the RES array. @@ -208,7 +204,7 @@ void mbedtls_havege_free( mbedtls_havege_state *hs ) if( hs == NULL ) return; - mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) ); + mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) ); } /* diff --git a/Externals/mbedtls/library/hkdf.c b/Externals/mbedtls/library/hkdf.c new file mode 100644 index 0000000000..82d8a429f4 --- /dev/null +++ b/Externals/mbedtls/library/hkdf.c @@ -0,0 +1,192 @@ +/* + * HKDF implementation -- RFC 5869 + * + * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HKDF_C) + +#include +#include "mbedtls/hkdf.h" +#include "mbedtls/platform_util.h" + +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ) +{ + int ret; + unsigned char prk[MBEDTLS_MD_MAX_SIZE]; + + ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); + + if( ret == 0 ) + { + ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), + info, info_len, okm, okm_len ); + } + + mbedtls_platform_zeroize( prk, sizeof( prk ) ); + + return( ret ); +} + +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ) +{ + unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; + + if( salt == NULL ) + { + size_t hash_len; + + if( salt_len != 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + hash_len = mbedtls_md_get_size( md ); + + if( hash_len == 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + salt = null_salt; + salt_len = hash_len; + } + + return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); +} + +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ) +{ + size_t hash_len; + size_t where = 0; + size_t n; + size_t t_len = 0; + size_t i; + int ret = 0; + mbedtls_md_context_t ctx; + unsigned char t[MBEDTLS_MD_MAX_SIZE]; + + if( okm == NULL ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + hash_len = mbedtls_md_get_size( md ); + + if( prk_len < hash_len || hash_len == 0 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + if( info == NULL ) + { + info = (const unsigned char *) ""; + info_len = 0; + } + + n = okm_len / hash_len; + + if( (okm_len % hash_len) != 0 ) + { + n++; + } + + /* + * Per RFC 5869 Section 2.3, okm_len must not exceed + * 255 times the hash length + */ + if( n > 255 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + mbedtls_md_init( &ctx ); + + if( (ret = mbedtls_md_setup( &ctx, md, 1) ) != 0 ) + { + goto exit; + } + + /* + * Compute T = T(1) | T(2) | T(3) | ... | T(N) + * Where T(N) is defined in RFC 5869 Section 2.3 + */ + for( i = 1; i <= n; i++ ) + { + size_t num_to_copy; + unsigned char c = i & 0xff; + + ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, t, t_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, info, info_len ); + if( ret != 0 ) + { + goto exit; + } + + /* The constant concatenated to the end of each T(n) is a single octet. + * */ + ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_finish( &ctx, t ); + if( ret != 0 ) + { + goto exit; + } + + num_to_copy = i != n ? hash_len : okm_len - where; + memcpy( okm + where, t, num_to_copy ); + where += hash_len; + t_len = hash_len; + } + +exit: + mbedtls_md_free( &ctx ); + mbedtls_platform_zeroize( t, sizeof( t ) ); + + return( ret ); +} + +#endif /* MBEDTLS_HKDF_C */ diff --git a/Externals/mbedtls/library/hmac_drbg.c b/Externals/mbedtls/library/hmac_drbg.c index bf5f9b5bd3..c50330e7d8 100644 --- a/Externals/mbedtls/library/hmac_drbg.c +++ b/Externals/mbedtls/library/hmac_drbg.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" +#include "mbedtls/platform_util.h" #include @@ -50,11 +51,6 @@ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_PLATFORM_C */ -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * HMAC_DRBG context initialization */ @@ -70,31 +66,60 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) /* * HMAC_DRBG update, using optional additional data (10.1.2.2) */ -void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) { size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; unsigned char sep[1]; unsigned char K[MBEDTLS_MD_MAX_SIZE]; + int ret; for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) { /* Step 1 or 4 */ - mbedtls_md_hmac_reset( &ctx->md_ctx ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + sep, 1 ) ) != 0 ) + goto exit; if( rounds == 2 ) - mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, K ); + { + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) + goto exit; /* Step 2 or 5 */ - mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; } + +exit: + mbedtls_platform_zeroize( K, sizeof( K ) ); + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + /* * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) */ @@ -112,10 +137,13 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, * Use the V memory location, which is currently all 0, to initialize the * MD context with an all-zero key. Then set V to its initial value. */ - mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, + mbedtls_md_get_size( md_info ) ) ) != 0 ) + return( ret ); memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); - mbedtls_hmac_drbg_update( ctx, data, data_len ); + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 ) + return( ret ); return( 0 ); } @@ -128,6 +156,7 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, { unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; size_t seedlen; + int ret; /* III. Check input length */ if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || @@ -139,7 +168,8 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); /* IV. Gather entropy_len bytes of entropy for the seed */ - if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed, ctx->entropy_len ) ) != 0 ) return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); seedlen = ctx->entropy_len; @@ -152,13 +182,16 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, } /* 2. Update state */ - mbedtls_hmac_drbg_update( ctx, seed, seedlen ); + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 ) + goto exit; /* 3. Reset reseed_counter */ ctx->reseed_counter = 1; +exit: /* 4. Done */ - return( 0 ); + mbedtls_platform_zeroize( seed, seedlen ); + return( ret ); } /* @@ -184,7 +217,8 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, * Use the V memory location, which is currently all 0, to initialize the * MD context with an all-zero key. Then set V to its initial value. */ - mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) + return( ret ); memset( ctx->V, 0x01, md_size ); ctx->f_entropy = f_entropy; @@ -277,16 +311,24 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng, /* 2. Use additional data if any */ if( additional != NULL && add_len != 0 ) - mbedtls_hmac_drbg_update( ctx, additional, add_len ); + { + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + } /* 3, 4, 5. Generate bytes */ while( left != 0 ) { size_t use_len = left > md_len ? md_len : left; - mbedtls_md_hmac_reset( &ctx->md_ctx ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; memcpy( out, ctx->V, use_len ); out += use_len; @@ -294,13 +336,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng, } /* 6. Update */ - mbedtls_hmac_drbg_update( ctx, additional, add_len ); + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; /* 7. Update reseed counter */ ctx->reseed_counter++; +exit: /* 8. Done */ - return( 0 ); + return( ret ); } /* @@ -338,7 +383,7 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) mbedtls_mutex_free( &ctx->mutex ); #endif mbedtls_md_free( &ctx->md_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); } #if defined(MBEDTLS_FS_IO) @@ -364,38 +409,44 @@ int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const cha exit: fclose( f ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + return( ret ); } int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) { - FILE *f; + int ret = 0; + FILE *f = NULL; size_t n; unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + unsigned char c; if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) { - fclose( f ); - return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; + goto exit; } - - if( fread( buf, 1, n, f ) != n ) + if( n == 0 || ferror( f ) ) { - fclose( f ); - return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; } - fclose( f ); + f = NULL; - mbedtls_hmac_drbg_update( ctx, buf, n ); + ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n ); +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); } #endif /* MBEDTLS_FS_IO */ diff --git a/Externals/mbedtls/library/md.c b/Externals/mbedtls/library/md.c index eda98f6361..303cdcbeeb 100644 --- a/Externals/mbedtls/library/md.c +++ b/Externals/mbedtls/library/md.c @@ -33,6 +33,7 @@ #include "mbedtls/md.h" #include "mbedtls/md_internal.h" +#include "mbedtls/platform_util.h" #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" @@ -48,11 +49,6 @@ #include #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Reminder: update profiles in x509_crt.c when adding a new hash! */ @@ -193,11 +189,12 @@ void mbedtls_md_free( mbedtls_md_context_t *ctx ) if( ctx->hmac_ctx != NULL ) { - mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); mbedtls_free( ctx->hmac_ctx ); } - mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); } int mbedtls_md_clone( mbedtls_md_context_t *dst, @@ -250,9 +247,7 @@ int mbedtls_md_starts( mbedtls_md_context_t *ctx ) if( ctx == NULL || ctx->md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - ctx->md_info->starts_func( ctx->md_ctx ); - - return( 0 ); + return( ctx->md_info->starts_func( ctx->md_ctx ) ); } int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) @@ -260,9 +255,7 @@ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, si if( ctx == NULL || ctx->md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - ctx->md_info->update_func( ctx->md_ctx, input, ilen ); - - return( 0 ); + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); } int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) @@ -270,9 +263,7 @@ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) if( ctx == NULL || ctx->md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - ctx->md_info->finish_func( ctx->md_ctx, output ); - - return( 0 ); + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); } int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, @@ -281,9 +272,7 @@ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, si if( md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - md_info->digest_func( input, ilen, output ); - - return( 0 ); + return( md_info->digest_func( input, ilen, output ) ); } #if defined(MBEDTLS_FS_IO) @@ -306,20 +295,20 @@ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigne if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) goto cleanup; - md_info->starts_func( ctx.md_ctx ); + if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 ) + goto cleanup; while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - md_info->update_func( ctx.md_ctx, buf, n ); + if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 ) + goto cleanup; if( ferror( f ) != 0 ) - { ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; - goto cleanup; - } - - md_info->finish_func( ctx.md_ctx, output ); + else + ret = md_info->finish_func( ctx.md_ctx, output ); cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); fclose( f ); mbedtls_md_free( &ctx ); @@ -329,6 +318,7 @@ cleanup: int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) { + int ret; unsigned char sum[MBEDTLS_MD_MAX_SIZE]; unsigned char *ipad, *opad; size_t i; @@ -338,9 +328,12 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, if( keylen > (size_t) ctx->md_info->block_size ) { - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, key, keylen ); - ctx->md_info->finish_func( ctx->md_ctx, sum ); + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 ) + goto cleanup; keylen = ctx->md_info->size; key = sum; @@ -358,12 +351,16 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, opad[i] = (unsigned char)( opad[i] ^ key[i] ); } - mbedtls_zeroize( sum, sizeof( sum ) ); + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); +cleanup: + mbedtls_platform_zeroize( sum, sizeof( sum ) ); - return( 0 ); + return( ret ); } int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) @@ -371,13 +368,12 @@ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *inpu if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - ctx->md_info->update_func( ctx->md_ctx, input, ilen ); - - return( 0 ); + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); } int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) { + int ret; unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; unsigned char *opad; @@ -386,17 +382,22 @@ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; - ctx->md_info->finish_func( ctx->md_ctx, tmp ); - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, opad, ctx->md_info->block_size ); - ctx->md_info->update_func( ctx->md_ctx, tmp, ctx->md_info->size ); - ctx->md_info->finish_func( ctx->md_ctx, output ); - - return( 0 ); + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); } int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) { + int ret; unsigned char *ipad; if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) @@ -404,15 +405,16 @@ int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) ipad = (unsigned char *) ctx->hmac_ctx; - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); - - return( 0 ); + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + return( ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ); } -int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) { mbedtls_md_context_t ctx; int ret; @@ -423,15 +425,19 @@ int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, mbedtls_md_init( &ctx ); if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) - return( ret ); + goto cleanup; - mbedtls_md_hmac_starts( &ctx, key, keylen ); - mbedtls_md_hmac_update( &ctx, input, ilen ); - mbedtls_md_hmac_finish( &ctx, output ); + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; +cleanup: mbedtls_md_free( &ctx ); - return( 0 ); + return( ret ); } int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) @@ -439,9 +445,7 @@ int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) if( ctx == NULL || ctx->md_info == NULL ) return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - ctx->md_info->process_func( ctx->md_ctx, data ); - - return( 0 ); + return( ctx->md_info->process_func( ctx->md_ctx, data ) ); } unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) diff --git a/Externals/mbedtls/library/md2.c b/Externals/mbedtls/library/md2.c index 8976701312..1c0b3df52d 100644 --- a/Externals/mbedtls/library/md2.c +++ b/Externals/mbedtls/library/md2.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_MD2_C) #include "mbedtls/md2.h" +#include "mbedtls/platform_util.h" #include @@ -48,11 +49,6 @@ #if !defined(MBEDTLS_MD2_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - static const unsigned char PI_SUBST[256] = { 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, @@ -93,7 +89,7 @@ void mbedtls_md2_free( mbedtls_md2_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_md2_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) ); } void mbedtls_md2_clone( mbedtls_md2_context *dst, @@ -105,16 +101,25 @@ void mbedtls_md2_clone( mbedtls_md2_context *dst, /* * MD2 context setup */ -void mbedtls_md2_starts( mbedtls_md2_context *ctx ) +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ) { memset( ctx->cksum, 0, 16 ); memset( ctx->state, 0, 46 ); memset( ctx->buffer, 0, 16 ); ctx->left = 0; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_starts( mbedtls_md2_context *ctx ) +{ + mbedtls_md2_starts_ret( ctx ); +} +#endif + #if !defined(MBEDTLS_MD2_PROCESS_ALT) -void mbedtls_md2_process( mbedtls_md2_context *ctx ) +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ) { int i, j; unsigned char t = 0; @@ -146,19 +151,31 @@ void mbedtls_md2_process( mbedtls_md2_context *ctx ) ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); t = ctx->cksum[i]; } + + return( 0 ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_process( mbedtls_md2_context *ctx ) +{ + mbedtls_internal_md2_process( ctx ); +} +#endif #endif /* !MBEDTLS_MD2_PROCESS_ALT */ /* * MD2 process buffer */ -void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ) +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; while( ilen > 0 ) { - if( ctx->left + ilen > 16 ) + if( ilen > 16 - ctx->left ) fill = 16 - ctx->left; else fill = ilen; @@ -172,16 +189,30 @@ void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, s if( ctx->left == 16 ) { ctx->left = 0; - mbedtls_md2_process( ctx ); + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); } } + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md2_update_ret( ctx, input, ilen ); +} +#endif + /* * MD2 final digest */ -void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ) { + int ret; size_t i; unsigned char x; @@ -190,36 +221,70 @@ void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) for( i = ctx->left; i < 16; i++ ) ctx->buffer[i] = x; - mbedtls_md2_process( ctx ); + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); memcpy( ctx->buffer, ctx->cksum, 16 ); - mbedtls_md2_process( ctx ); + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); memcpy( output, ctx->state, 16 ); + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md2_finish_ret( ctx, output ); +} +#endif + #endif /* !MBEDTLS_MD2_ALT */ /* * output = MD2( input buffer ) */ -void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) { + int ret; mbedtls_md2_context ctx; mbedtls_md2_init( &ctx ); - mbedtls_md2_starts( &ctx ); - mbedtls_md2_update( &ctx, input, ilen ); - mbedtls_md2_finish( &ctx, output ); + + if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: mbedtls_md2_free( &ctx ); + + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md2_ret( input, ilen, output ); +} +#endif + #if defined(MBEDTLS_SELF_TEST) /* * RFC 1319 test vectors */ -static const char md2_test_str[7][81] = +static const unsigned char md2_test_str[7][81] = { { "" }, { "a" }, @@ -227,10 +292,15 @@ static const char md2_test_str[7][81] = { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ + { "12345678901234567890123456789012345678901234567890123456789012" "345678901234567890" } }; +static const size_t md2_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + static const unsigned char md2_test_sum[7][16] = { { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, @@ -254,7 +324,7 @@ static const unsigned char md2_test_sum[7][16] = */ int mbedtls_md2_self_test( int verbose ) { - int i; + int i, ret = 0; unsigned char md2sum[16]; for( i = 0; i < 7; i++ ) @@ -262,15 +332,14 @@ int mbedtls_md2_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " MD2 test #%d: ", i + 1 ); - mbedtls_md2( (unsigned char *) md2_test_str[i], - strlen( md2_test_str[i] ), md2sum ); + ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum ); + if( ret != 0 ) + goto fail; if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); + ret = 1; + goto fail; } if( verbose != 0 ) @@ -281,6 +350,12 @@ int mbedtls_md2_self_test( int verbose ) mbedtls_printf( "\n" ); return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); } #endif /* MBEDTLS_SELF_TEST */ diff --git a/Externals/mbedtls/library/md4.c b/Externals/mbedtls/library/md4.c index 11a77e3ae4..3f8ddff31d 100644 --- a/Externals/mbedtls/library/md4.c +++ b/Externals/mbedtls/library/md4.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_MD4_C) #include "mbedtls/md4.h" +#include "mbedtls/platform_util.h" #include @@ -48,11 +49,6 @@ #if !defined(MBEDTLS_MD4_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (little endian) */ @@ -86,7 +82,7 @@ void mbedtls_md4_free( mbedtls_md4_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) ); } void mbedtls_md4_clone( mbedtls_md4_context *dst, @@ -98,7 +94,7 @@ void mbedtls_md4_clone( mbedtls_md4_context *dst, /* * MD4 context setup */ -void mbedtls_md4_starts( mbedtls_md4_context *ctx ) +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -107,10 +103,20 @@ void mbedtls_md4_starts( mbedtls_md4_context *ctx ) ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_starts( mbedtls_md4_context *ctx ) +{ + mbedtls_md4_starts_ret( ctx ); +} +#endif + #if !defined(MBEDTLS_MD4_PROCESS_ALT) -void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ) +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) { uint32_t X[16], A, B, C, D; @@ -211,19 +217,32 @@ void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ctx->state[1] += B; ctx->state[2] += C; ctx->state[3] += D; + + return( 0 ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md4_process( ctx, data ); +} +#endif #endif /* !MBEDTLS_MD4_PROCESS_ALT */ /* * MD4 process buffer */ -void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ) +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; uint32_t left; if( ilen == 0 ) - return; + return( 0 ); left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -238,7 +257,10 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s { memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); - mbedtls_md4_process( ctx, ctx->buffer ); + + if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; ilen -= fill; left = 0; @@ -246,7 +268,9 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s while( ilen >= 64 ) { - mbedtls_md4_process( ctx, input ); + if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) + return( ret ); + input += 64; ilen -= 64; } @@ -256,8 +280,19 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s memcpy( (void *) (ctx->buffer + left), (void *) input, ilen ); } + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md4_update_ret( ctx, input, ilen ); +} +#endif + static const unsigned char md4_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -269,8 +304,10 @@ static const unsigned char md4_padding[64] = /* * MD4 final digest */ -void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ) { + int ret; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; @@ -285,37 +322,74 @@ void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn ); - mbedtls_md4_update( ctx, msglen, 8 ); + ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); + if( ret != 0 ) + return( ret ); + + if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE( ctx->state[2], output, 8 ); PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md4_finish_ret( ctx, output ); +} +#endif + #endif /* !MBEDTLS_MD4_ALT */ /* * output = MD4( input buffer ) */ -void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) { + int ret; mbedtls_md4_context ctx; mbedtls_md4_init( &ctx ); - mbedtls_md4_starts( &ctx ); - mbedtls_md4_update( &ctx, input, ilen ); - mbedtls_md4_finish( &ctx, output ); + + if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: mbedtls_md4_free( &ctx ); + + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md4_ret( input, ilen, output ); +} +#endif + #if defined(MBEDTLS_SELF_TEST) /* * RFC 1320 test vectors */ -static const char md4_test_str[7][81] = +static const unsigned char md4_test_str[7][81] = { { "" }, { "a" }, @@ -323,10 +397,15 @@ static const char md4_test_str[7][81] = { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ + { "12345678901234567890123456789012345678901234567890123456789012" "345678901234567890" } }; +static const size_t md4_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + static const unsigned char md4_test_sum[7][16] = { { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, @@ -350,7 +429,7 @@ static const unsigned char md4_test_sum[7][16] = */ int mbedtls_md4_self_test( int verbose ) { - int i; + int i, ret = 0; unsigned char md4sum[16]; for( i = 0; i < 7; i++ ) @@ -358,15 +437,14 @@ int mbedtls_md4_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " MD4 test #%d: ", i + 1 ); - mbedtls_md4( (unsigned char *) md4_test_str[i], - strlen( md4_test_str[i] ), md4sum ); + ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); + if( ret != 0 ) + goto fail; if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); + ret = 1; + goto fail; } if( verbose != 0 ) @@ -377,6 +455,12 @@ int mbedtls_md4_self_test( int verbose ) mbedtls_printf( "\n" ); return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); } #endif /* MBEDTLS_SELF_TEST */ diff --git a/Externals/mbedtls/library/md5.c b/Externals/mbedtls/library/md5.c index 5d972dc9dd..2a740cda81 100644 --- a/Externals/mbedtls/library/md5.c +++ b/Externals/mbedtls/library/md5.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_MD5_C) #include "mbedtls/md5.h" +#include "mbedtls/platform_util.h" #include @@ -47,11 +48,6 @@ #if !defined(MBEDTLS_MD5_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (little endian) */ @@ -85,7 +81,7 @@ void mbedtls_md5_free( mbedtls_md5_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); } void mbedtls_md5_clone( mbedtls_md5_context *dst, @@ -97,7 +93,7 @@ void mbedtls_md5_clone( mbedtls_md5_context *dst, /* * MD5 context setup */ -void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -106,10 +102,20 @@ void mbedtls_md5_starts( mbedtls_md5_context *ctx ) ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + mbedtls_md5_starts_ret( ctx ); +} +#endif + #if !defined(MBEDTLS_MD5_PROCESS_ALT) -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ) +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) { uint32_t X[16], A, B, C, D; @@ -230,19 +236,32 @@ void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ctx->state[1] += B; ctx->state[2] += C; ctx->state[3] += D; + + return( 0 ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md5_process( ctx, data ); +} +#endif #endif /* !MBEDTLS_MD5_PROCESS_ALT */ /* * MD5 process buffer */ -void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; uint32_t left; if( ilen == 0 ) - return; + return( 0 ); left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -256,7 +275,9 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_md5_process( ctx, ctx->buffer ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; ilen -= fill; left = 0; @@ -264,7 +285,9 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s while( ilen >= 64 ) { - mbedtls_md5_process( ctx, input ); + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + input += 64; ilen -= 64; } @@ -273,60 +296,122 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s { memcpy( (void *) (ctx->buffer + left), input, ilen ); } + + return( 0 ); } -static const unsigned char md5_padding[64] = +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; + mbedtls_md5_update_ret( ctx, input, ilen ); +} +#endif /* * MD5 final digest */ -void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) { - uint32_t last, padn; + int ret; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); + PUT_UINT32_LE( low, ctx->buffer, 56 ); + PUT_UINT32_LE( high, ctx->buffer, 60 ); - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_md5_update( ctx, md5_padding, padn ); - mbedtls_md5_update( ctx, msglen, 8 ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + /* + * Output final state + */ PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE( ctx->state[2], output, 8 ); PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md5_finish_ret( ctx, output ); +} +#endif + #endif /* !MBEDTLS_MD5_ALT */ /* * output = MD5( input buffer ) */ -void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) { + int ret; mbedtls_md5_context ctx; mbedtls_md5_init( &ctx ); - mbedtls_md5_starts( &ctx ); - mbedtls_md5_update( &ctx, input, ilen ); - mbedtls_md5_finish( &ctx, output ); + + if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: mbedtls_md5_free( &ctx ); + + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md5_ret( input, ilen, output ); +} +#endif + #if defined(MBEDTLS_SELF_TEST) /* * RFC 1321 test vectors @@ -339,11 +424,11 @@ static const unsigned char md5_test_buf[7][81] = { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ + { "12345678901234567890123456789012345678901234567890123456789012" "345678901234567890" } }; -static const int md5_test_buflen[7] = +static const size_t md5_test_buflen[7] = { 0, 1, 3, 14, 26, 62, 80 }; @@ -371,7 +456,7 @@ static const unsigned char md5_test_sum[7][16] = */ int mbedtls_md5_self_test( int verbose ) { - int i; + int i, ret = 0; unsigned char md5sum[16]; for( i = 0; i < 7; i++ ) @@ -379,14 +464,14 @@ int mbedtls_md5_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " MD5 test #%d: ", i + 1 ); - mbedtls_md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); + ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); + ret = 1; + goto fail; } if( verbose != 0 ) @@ -397,6 +482,12 @@ int mbedtls_md5_self_test( int verbose ) mbedtls_printf( "\n" ); return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); } #endif /* MBEDTLS_SELF_TEST */ diff --git a/Externals/mbedtls/library/md_wrap.c b/Externals/mbedtls/library/md_wrap.c index 2cfcae200e..32f0871976 100644 --- a/Externals/mbedtls/library/md_wrap.c +++ b/Externals/mbedtls/library/md_wrap.c @@ -71,20 +71,20 @@ #if defined(MBEDTLS_MD2_C) -static void md2_starts_wrap( void *ctx ) +static int md2_starts_wrap( void *ctx ) { - mbedtls_md2_starts( (mbedtls_md2_context *) ctx ); + return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) ); } -static void md2_update_wrap( void *ctx, const unsigned char *input, +static int md2_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { - mbedtls_md2_update( (mbedtls_md2_context *) ctx, input, ilen ); + return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) ); } -static void md2_finish_wrap( void *ctx, unsigned char *output ) +static int md2_finish_wrap( void *ctx, unsigned char *output ) { - mbedtls_md2_finish( (mbedtls_md2_context *) ctx, output ); + return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) ); } static void *md2_ctx_alloc( void ) @@ -109,11 +109,11 @@ static void md2_clone_wrap( void *dst, const void *src ) (const mbedtls_md2_context *) src ); } -static void md2_process_wrap( void *ctx, const unsigned char *data ) +static int md2_process_wrap( void *ctx, const unsigned char *data ) { ((void) data); - mbedtls_md2_process( (mbedtls_md2_context *) ctx ); + return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) ); } const mbedtls_md_info_t mbedtls_md2_info = { @@ -124,7 +124,7 @@ const mbedtls_md_info_t mbedtls_md2_info = { md2_starts_wrap, md2_update_wrap, md2_finish_wrap, - mbedtls_md2, + mbedtls_md2_ret, md2_ctx_alloc, md2_ctx_free, md2_clone_wrap, @@ -135,20 +135,20 @@ const mbedtls_md_info_t mbedtls_md2_info = { #if defined(MBEDTLS_MD4_C) -static void md4_starts_wrap( void *ctx ) +static int md4_starts_wrap( void *ctx ) { - mbedtls_md4_starts( (mbedtls_md4_context *) ctx ); + return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) ); } -static void md4_update_wrap( void *ctx, const unsigned char *input, +static int md4_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { - mbedtls_md4_update( (mbedtls_md4_context *) ctx, input, ilen ); + return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) ); } -static void md4_finish_wrap( void *ctx, unsigned char *output ) +static int md4_finish_wrap( void *ctx, unsigned char *output ) { - mbedtls_md4_finish( (mbedtls_md4_context *) ctx, output ); + return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) ); } static void *md4_ctx_alloc( void ) @@ -170,12 +170,12 @@ static void md4_ctx_free( void *ctx ) static void md4_clone_wrap( void *dst, const void *src ) { mbedtls_md4_clone( (mbedtls_md4_context *) dst, - (const mbedtls_md4_context *) src ); + (const mbedtls_md4_context *) src ); } -static void md4_process_wrap( void *ctx, const unsigned char *data ) +static int md4_process_wrap( void *ctx, const unsigned char *data ) { - mbedtls_md4_process( (mbedtls_md4_context *) ctx, data ); + return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) ); } const mbedtls_md_info_t mbedtls_md4_info = { @@ -186,7 +186,7 @@ const mbedtls_md_info_t mbedtls_md4_info = { md4_starts_wrap, md4_update_wrap, md4_finish_wrap, - mbedtls_md4, + mbedtls_md4_ret, md4_ctx_alloc, md4_ctx_free, md4_clone_wrap, @@ -197,20 +197,20 @@ const mbedtls_md_info_t mbedtls_md4_info = { #if defined(MBEDTLS_MD5_C) -static void md5_starts_wrap( void *ctx ) +static int md5_starts_wrap( void *ctx ) { - mbedtls_md5_starts( (mbedtls_md5_context *) ctx ); + return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) ); } -static void md5_update_wrap( void *ctx, const unsigned char *input, +static int md5_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { - mbedtls_md5_update( (mbedtls_md5_context *) ctx, input, ilen ); + return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) ); } -static void md5_finish_wrap( void *ctx, unsigned char *output ) +static int md5_finish_wrap( void *ctx, unsigned char *output ) { - mbedtls_md5_finish( (mbedtls_md5_context *) ctx, output ); + return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) ); } static void *md5_ctx_alloc( void ) @@ -232,12 +232,12 @@ static void md5_ctx_free( void *ctx ) static void md5_clone_wrap( void *dst, const void *src ) { mbedtls_md5_clone( (mbedtls_md5_context *) dst, - (const mbedtls_md5_context *) src ); + (const mbedtls_md5_context *) src ); } -static void md5_process_wrap( void *ctx, const unsigned char *data ) +static int md5_process_wrap( void *ctx, const unsigned char *data ) { - mbedtls_md5_process( (mbedtls_md5_context *) ctx, data ); + return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) ); } const mbedtls_md_info_t mbedtls_md5_info = { @@ -248,7 +248,7 @@ const mbedtls_md_info_t mbedtls_md5_info = { md5_starts_wrap, md5_update_wrap, md5_finish_wrap, - mbedtls_md5, + mbedtls_md5_ret, md5_ctx_alloc, md5_ctx_free, md5_clone_wrap, @@ -259,20 +259,22 @@ const mbedtls_md_info_t mbedtls_md5_info = { #if defined(MBEDTLS_RIPEMD160_C) -static void ripemd160_starts_wrap( void *ctx ) +static int ripemd160_starts_wrap( void *ctx ) { - mbedtls_ripemd160_starts( (mbedtls_ripemd160_context *) ctx ); + return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) ); } -static void ripemd160_update_wrap( void *ctx, const unsigned char *input, +static int ripemd160_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { - mbedtls_ripemd160_update( (mbedtls_ripemd160_context *) ctx, input, ilen ); + return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx, + input, ilen ) ); } -static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) +static int ripemd160_finish_wrap( void *ctx, unsigned char *output ) { - mbedtls_ripemd160_finish( (mbedtls_ripemd160_context *) ctx, output ); + return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx, + output ) ); } static void *ripemd160_ctx_alloc( void ) @@ -297,9 +299,10 @@ static void ripemd160_clone_wrap( void *dst, const void *src ) (const mbedtls_ripemd160_context *) src ); } -static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) +static int ripemd160_process_wrap( void *ctx, const unsigned char *data ) { - mbedtls_ripemd160_process( (mbedtls_ripemd160_context *) ctx, data ); + return( mbedtls_internal_ripemd160_process( + (mbedtls_ripemd160_context *) ctx, data ) ); } const mbedtls_md_info_t mbedtls_ripemd160_info = { @@ -310,7 +313,7 @@ const mbedtls_md_info_t mbedtls_ripemd160_info = { ripemd160_starts_wrap, ripemd160_update_wrap, ripemd160_finish_wrap, - mbedtls_ripemd160, + mbedtls_ripemd160_ret, ripemd160_ctx_alloc, ripemd160_ctx_free, ripemd160_clone_wrap, @@ -321,20 +324,21 @@ const mbedtls_md_info_t mbedtls_ripemd160_info = { #if defined(MBEDTLS_SHA1_C) -static void sha1_starts_wrap( void *ctx ) +static int sha1_starts_wrap( void *ctx ) { - mbedtls_sha1_starts( (mbedtls_sha1_context *) ctx ); + return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) ); } -static void sha1_update_wrap( void *ctx, const unsigned char *input, +static int sha1_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { - mbedtls_sha1_update( (mbedtls_sha1_context *) ctx, input, ilen ); + return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx, + input, ilen ) ); } -static void sha1_finish_wrap( void *ctx, unsigned char *output ) +static int sha1_finish_wrap( void *ctx, unsigned char *output ) { - mbedtls_sha1_finish( (mbedtls_sha1_context *) ctx, output ); + return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) ); } static void *sha1_ctx_alloc( void ) @@ -359,9 +363,10 @@ static void sha1_ctx_free( void *ctx ) mbedtls_free( ctx ); } -static void sha1_process_wrap( void *ctx, const unsigned char *data ) +static int sha1_process_wrap( void *ctx, const unsigned char *data ) { - mbedtls_sha1_process( (mbedtls_sha1_context *) ctx, data ); + return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx, + data ) ); } const mbedtls_md_info_t mbedtls_sha1_info = { @@ -372,7 +377,7 @@ const mbedtls_md_info_t mbedtls_sha1_info = { sha1_starts_wrap, sha1_update_wrap, sha1_finish_wrap, - mbedtls_sha1, + mbedtls_sha1_ret, sha1_ctx_alloc, sha1_ctx_free, sha1_clone_wrap, @@ -386,26 +391,28 @@ const mbedtls_md_info_t mbedtls_sha1_info = { */ #if defined(MBEDTLS_SHA256_C) -static void sha224_starts_wrap( void *ctx ) +static int sha224_starts_wrap( void *ctx ) { - mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 1 ); + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) ); } -static void sha224_update_wrap( void *ctx, const unsigned char *input, +static int sha224_update_wrap( void *ctx, const unsigned char *input, size_t ilen ) { - mbedtls_sha256_update( (mbedtls_sha256_context *) ctx, input, ilen ); + return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx, + input, ilen ) ); } -static void sha224_finish_wrap( void *ctx, unsigned char *output ) +static int sha224_finish_wrap( void *ctx, unsigned char *output ) { - mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); + return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx, + output ) ); } -static void sha224_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) +static int sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) { - mbedtls_sha256( input, ilen, output, 1 ); + return( mbedtls_sha256_ret( input, ilen, output, 1 ) ); } static void *sha224_ctx_alloc( void ) @@ -430,9 +437,10 @@ static void sha224_clone_wrap( void *dst, const void *src ) (const mbedtls_sha256_context *) src ); } -static void sha224_process_wrap( void *ctx, const unsigned char *data ) +static int sha224_process_wrap( void *ctx, const unsigned char *data ) { - mbedtls_sha256_process( (mbedtls_sha256_context *) ctx, data ); + return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx, + data ) ); } const mbedtls_md_info_t mbedtls_sha224_info = { @@ -450,15 +458,15 @@ const mbedtls_md_info_t mbedtls_sha224_info = { sha224_process_wrap, }; -static void sha256_starts_wrap( void *ctx ) +static int sha256_starts_wrap( void *ctx ) { - mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 0 ); + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) ); } -static void sha256_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) +static int sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) { - mbedtls_sha256( input, ilen, output, 0 ); + return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); } const mbedtls_md_info_t mbedtls_sha256_info = { @@ -480,26 +488,28 @@ const mbedtls_md_info_t mbedtls_sha256_info = { #if defined(MBEDTLS_SHA512_C) -static void sha384_starts_wrap( void *ctx ) +static int sha384_starts_wrap( void *ctx ) { - mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 1 ); + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) ); } -static void sha384_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) +static int sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) { - mbedtls_sha512_update( (mbedtls_sha512_context *) ctx, input, ilen ); + return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx, + input, ilen ) ); } -static void sha384_finish_wrap( void *ctx, unsigned char *output ) +static int sha384_finish_wrap( void *ctx, unsigned char *output ) { - mbedtls_sha512_finish( (mbedtls_sha512_context *) ctx, output ); + return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx, + output ) ); } -static void sha384_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) +static int sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) { - mbedtls_sha512( input, ilen, output, 1 ); + return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); } static void *sha384_ctx_alloc( void ) @@ -524,9 +534,10 @@ static void sha384_clone_wrap( void *dst, const void *src ) (const mbedtls_sha512_context *) src ); } -static void sha384_process_wrap( void *ctx, const unsigned char *data ) +static int sha384_process_wrap( void *ctx, const unsigned char *data ) { - mbedtls_sha512_process( (mbedtls_sha512_context *) ctx, data ); + return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx, + data ) ); } const mbedtls_md_info_t mbedtls_sha384_info = { @@ -544,15 +555,15 @@ const mbedtls_md_info_t mbedtls_sha384_info = { sha384_process_wrap, }; -static void sha512_starts_wrap( void *ctx ) +static int sha512_starts_wrap( void *ctx ) { - mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 0 ); + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) ); } -static void sha512_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) +static int sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) { - mbedtls_sha512( input, ilen, output, 0 ); + return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); } const mbedtls_md_info_t mbedtls_sha512_info = { diff --git a/Externals/mbedtls/library/memory_buffer_alloc.c b/Externals/mbedtls/library/memory_buffer_alloc.c index 545d5a2c32..51ea7c41d7 100644 --- a/Externals/mbedtls/library/memory_buffer_alloc.c +++ b/Externals/mbedtls/library/memory_buffer_alloc.c @@ -31,6 +31,7 @@ /* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C is dependent upon MBEDTLS_PLATFORM_C */ #include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" #include @@ -42,11 +43,6 @@ #include "mbedtls/threading.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - #define MAGIC1 0xFF00AA55 #define MAGIC2 0xEE119966 #define MAX_BT 20 @@ -113,7 +109,7 @@ static void debug_header( memory_header *hdr ) #endif } -static void debug_chain() +static void debug_chain( void ) { memory_header *cur = heap.first; @@ -180,11 +176,11 @@ static int verify_header( memory_header *hdr ) return( 0 ); } -static int verify_chain() +static int verify_chain( void ) { - memory_header *prv = heap.first, *cur = heap.first->next; + memory_header *prv = heap.first, *cur; - if( verify_header( heap.first ) != 0 ) + if( prv == NULL || verify_header( prv ) != 0 ) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf( stderr, "FATAL: verification of first header " @@ -202,6 +198,8 @@ static int verify_chain() return( 1 ); } + cur = heap.first->next; + while( cur != NULL ) { if( verify_header( cur ) != 0 ) @@ -245,7 +243,9 @@ static void *buffer_alloc_calloc( size_t n, size_t size ) original_len = len = n * size; - if( n != 0 && len / n != size ) + if( n == 0 || size == 0 || len / n != size ) + return( NULL ); + else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) return( NULL ); if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) @@ -386,7 +386,7 @@ static void buffer_alloc_free( void *ptr ) if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) return; - if( p < heap.buf || p > heap.buf + heap.len ) + if( p < heap.buf || p >= heap.buf + heap.len ) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " @@ -500,13 +500,13 @@ void mbedtls_memory_buffer_set_verify( int verify ) heap.verify = verify; } -int mbedtls_memory_buffer_alloc_verify() +int mbedtls_memory_buffer_alloc_verify( void ) { return verify_chain(); } #if defined(MBEDTLS_MEMORY_DEBUG) -void mbedtls_memory_buffer_alloc_status() +void mbedtls_memory_buffer_alloc_status( void ) { mbedtls_fprintf( stderr, "Current use: %zu blocks / %zu bytes, max: %zu blocks / " @@ -518,7 +518,9 @@ void mbedtls_memory_buffer_alloc_status() heap.alloc_count, heap.free_count ); if( heap.first->next == NULL ) + { mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + } else { mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); @@ -570,8 +572,7 @@ static void buffer_alloc_free_mutexed( void *ptr ) void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) { - memset( &heap, 0, sizeof(buffer_alloc_ctx) ); - memset( buf, 0, len ); + memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init( &heap.mutex ); @@ -581,31 +582,35 @@ void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); #endif - if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return; + else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) { /* Adjust len first since buf is used in the computation */ len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE - - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE - - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; } + memset( buf, 0, len ); + heap.buf = buf; heap.len = len; - heap.first = (memory_header *) buf; - heap.first->size = len - sizeof(memory_header); + heap.first = (memory_header *)buf; + heap.first->size = len - sizeof( memory_header ); heap.first->magic1 = MAGIC1; heap.first->magic2 = MAGIC2; heap.first_free = heap.first; } -void mbedtls_memory_buffer_alloc_free() +void mbedtls_memory_buffer_alloc_free( void ) { #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free( &heap.mutex ); #endif - mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) ); + mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) ); } #if defined(MBEDTLS_SELF_TEST) @@ -620,7 +625,7 @@ static int check_pointer( void *p ) return( 0 ); } -static int check_all_free( ) +static int check_all_free( void ) { if( #if defined(MBEDTLS_MEMORY_DEBUG) diff --git a/Externals/mbedtls/library/net_sockets.c b/Externals/mbedtls/library/net_sockets.c index cc06cbfad3..816b1303df 100644 --- a/Externals/mbedtls/library/net_sockets.c +++ b/Externals/mbedtls/library/net_sockets.c @@ -19,6 +19,11 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must + * be set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -28,7 +33,8 @@ #if defined(MBEDTLS_NET_C) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" #endif @@ -45,11 +51,14 @@ #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) -#ifdef _WIN32_WINNT +#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR ) + +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) #undef _WIN32_WINNT -#endif /* Enables getaddrinfo() & Co */ #define _WIN32_WINNT 0x0501 +#endif + #include #include @@ -63,8 +72,8 @@ #endif #endif /* _MSC_VER */ -#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0) -#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0) +#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) +#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) #define close(fd) closesocket(fd) static int wsa_init_done = 0; @@ -82,10 +91,12 @@ static int wsa_init_done = 0; #include #include +#define IS_EINTR( ret ) ( ( ret ) == EINTR ) + #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* Some MS functions want int and MSVC warns if we pass size_t, - * but the standard fucntions use socklen_t, so cast only for MSVC */ + * but the standard functions use socklen_t, so cast only for MSVC */ #if defined(_MSC_VER) #define MSVC_INT_CAST (int) #else @@ -133,7 +144,8 @@ void mbedtls_net_init( mbedtls_net_context *ctx ) /* * Initiate a TCP connection with host:port and the given protocol */ -int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ) +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) { int ret; struct addrinfo hints, *addr_list, *cur; @@ -238,7 +250,7 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char } } - /* I we ever get there, it's a success */ + /* Bind was successful */ ret = 0; break; } @@ -269,13 +281,18 @@ static int net_would_block( const mbedtls_net_context *ctx ) */ static int net_would_block( const mbedtls_net_context *ctx ) { + int err = errno; + /* * Never return 'WOULD BLOCK' on a non-blocking socket */ if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) + { + errno = err; return( 0 ); + } - switch( errno ) + switch( errno = err ) { #if defined EAGAIN case EAGAIN: @@ -322,7 +339,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, { /* TCP: actual accept() */ ret = client_ctx->fd = (int) accept( bind_ctx->fd, - (struct sockaddr *) &client_addr, &n ); + (struct sockaddr *) &client_addr, &n ); } else { @@ -432,6 +449,72 @@ int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) #endif } +/* + * Check if data is available on the socket + */ + +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) +{ + int ret; + struct timeval tv; + + fd_set read_fds; + fd_set write_fds; + + int fd = ctx->fd; + + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + /* Ensure that memory sanitizers consider read_fds and write_fds as + * initialized even on platforms such as Glibc/x86_64 where FD_ZERO + * is implemented in assembly. */ + memset( &read_fds, 0, sizeof( read_fds ) ); + memset( &write_fds, 0, sizeof( write_fds ) ); +#endif +#endif + + FD_ZERO( &read_fds ); + if( rw & MBEDTLS_NET_POLL_READ ) + { + rw &= ~MBEDTLS_NET_POLL_READ; + FD_SET( fd, &read_fds ); + } + + FD_ZERO( &write_fds ); + if( rw & MBEDTLS_NET_POLL_WRITE ) + { + rw &= ~MBEDTLS_NET_POLL_WRITE; + FD_SET( fd, &write_fds ); + } + + if( rw != 0 ) + return( MBEDTLS_ERR_NET_BAD_INPUT_DATA ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + do + { + ret = select( fd + 1, &read_fds, &write_fds, NULL, + timeout == (uint32_t) -1 ? NULL : &tv ); + } + while( IS_EINTR( ret ) ); + + if( ret < 0 ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + + ret = 0; + if( FD_ISSET( fd, &read_fds ) ) + ret |= MBEDTLS_NET_POLL_READ; + if( FD_ISSET( fd, &write_fds ) ) + ret |= MBEDTLS_NET_POLL_WRITE; + + return( ret ); +} + /* * Portable usleep helper */ @@ -491,8 +574,8 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) /* * Read at most 'len' characters, blocking for at most 'timeout' ms */ -int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ) +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, + size_t len, uint32_t timeout ) { int ret; struct timeval tv; diff --git a/Externals/mbedtls/library/nist_kw.c b/Externals/mbedtls/library/nist_kw.c new file mode 100644 index 0000000000..317a2426ae --- /dev/null +++ b/Externals/mbedtls/library/nist_kw.c @@ -0,0 +1,755 @@ +/* + * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes + * only + * + * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ +/* + * Definition of Key Wrapping: + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" + * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" + * + * Note: RFC 3394 defines different methodology for intermediate operations for + * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_NIST_KW_C) + +#include "mbedtls/nist_kw.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_NIST_KW_ALT) + +#define KW_SEMIBLOCK_LENGTH 8 +#define MIN_SEMIBLOCKS_COUNT 3 + +/* constant-time buffer comparison */ +static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( diff ); +} + +/*! The 64-bit default integrity check value (ICV) for KW mode. */ +static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; +/*! The 32-bit default integrity check value (ICV) for KWP mode. */ +static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; + +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +/* + * Initialize context + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); +} + +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, + keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* + * SP 800-38F currently defines AES cipher as the only block cipher allowed: + * "For KW and KWP, the underlying block cipher shall be approved, and the + * block size shall be 128 bits. Currently, the AES block cipher, with key + * lengths of 128, 192, or 256 bits, is the only block cipher that fits + * this profile." + * Currently we don't support other 128 bit block ciphers for key wrapping, + * such as Camellia and Aria. + */ + if( cipher != MBEDTLS_CIPHER_ID_AES ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + is_wrap ? MBEDTLS_ENCRYPT : + MBEDTLS_DECRYPT ) + ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); +} + +/* + * Helper function for Xoring the uint64_t "t" with the encrypted A. + * Defined in NIST SP 800-38F section 6.1 + */ +static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) +{ + size_t i = 0; + for( i = 0; i < sizeof( t ); i++ ) + { + A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; + } +} + +/* + * KW-AE as defined in SP 800-38F section 6.2 + * KWP-AE as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t semiblocks = 0; + size_t s; + size_t olen, padlen = 0; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; + unsigned char *A = output; + + *out_len = 0; + /* + * Generate the String to work on + */ + if( mode == MBEDTLS_KW_MODE_KW ) + { + if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KW + * must be between 2 to 2^54-1 semiblocks inclusive. + */ + if( in_len < 16 || +#if SIZE_MAX > 0x1FFFFFFFFFFFFF8 + in_len > 0x1FFFFFFFFFFFFF8 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); + memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + } + else + { + if( in_len % 8 != 0 ) + { + padlen = ( 8 - ( in_len % 8 ) ); + } + + if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KWP + * must be between 1 and 2^32-1 octets inclusive. + */ + if( in_len < 1 +#if SIZE_MAX > 0xFFFFFFFF + || in_len > 0xFFFFFFFF +#endif + ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); + PUT_UINT32_BE( ( in_len & 0xffffffff ), output, + KW_SEMIBLOCK_LENGTH / 2 ); + + memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); + } + semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; + + s = 6 * ( semiblocks - 1 ); + + if( mode == MBEDTLS_KW_MODE_KWP + && in_len <= KW_SEMIBLOCK_LENGTH ) + { + memcpy( inbuff, output, 16 ); + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, output, &olen ); + if( ret != 0 ) + goto cleanup; + } + else + { + /* + * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 + */ + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + goto cleanup; + } + + /* Calculate intermediate values */ + for( t = 1; t <= s; t++ ) + { + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + calc_a_xor_t( A, t ); + + memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + R2 += KW_SEMIBLOCK_LENGTH; + if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) + R2 = output + KW_SEMIBLOCK_LENGTH; + } + } + + *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; + +cleanup: + + if( ret != 0) + { + memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); + } + mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); + + return( ret ); +} + +/* + * W-1 function as defined in RFC 3394 section 2.2.2 + * This function assumes the following: + * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. + * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. + * 3. Minimal number of semiblocks is 3. + * 4. A is a buffer to hold the first semiblock of the input buffer. + */ +static int unwrap( mbedtls_nist_kw_context *ctx, + const unsigned char *input, size_t semiblocks, + unsigned char A[KW_SEMIBLOCK_LENGTH], + unsigned char *output, size_t* out_len ) +{ + int ret = 0; + const size_t s = 6 * ( semiblocks - 1 ); + size_t olen; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + *out_len = 0; + + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( A, input, KW_SEMIBLOCK_LENGTH ); + memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + + /* Calculate intermediate values */ + for( t = s; t >= 1; t-- ) + { + calc_a_xor_t( A, t ); + + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + + /* Set R as LSB64 of outbuff */ + memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + + if( R == output ) + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + else + R -= KW_SEMIBLOCK_LENGTH; + } + + *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; + +cleanup: + if( ret != 0) + memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + + return( ret ); +} + +/* + * KW-AD as defined in SP 800-38F section 6.2 + * KWP-AD as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t i, olen; + unsigned char A[KW_SEMIBLOCK_LENGTH]; + unsigned char diff, bad_padding = 0; + + *out_len = 0; + if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( mode == MBEDTLS_KW_MODE_KW ) + { + /* + * According to SP 800-38F Table 1, the ciphertext length for KW + * must be between 3 to 2^54 semiblocks inclusive. + */ + if( in_len < 24 || +#if SIZE_MAX > 0x200000000000000 + in_len > 0x200000000000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto cleanup; + } + + } + else if( mode == MBEDTLS_KW_MODE_KWP ) + { + size_t padlen = 0; + uint32_t Plen; + /* + * According to SP 800-38F Table 1, the ciphertext length for KWP + * must be between 2 to 2^29 semiblocks inclusive. + */ + if( in_len < KW_SEMIBLOCK_LENGTH * 2 || +#if SIZE_MAX > 0x100000000 + in_len > 0x100000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) + { + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + input, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + *out_len = KW_SEMIBLOCK_LENGTH; + } + else + { + /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + } + + /* Check ICV in "constant-time" */ + diff = mbedtls_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + GET_UINT32_BE( Plen, A, KW_SEMIBLOCK_LENGTH / 2 ); + + /* + * Plen is the length of the plaintext, when the input is valid. + * If Plen is larger than the plaintext and padding, padlen will be + * larger than 8, because of the type wrap around. + */ + padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; + if ( padlen > 7 ) + { + padlen &= 7; + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + /* Check padding in "constant-time" */ + for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) + { + if( i >= KW_SEMIBLOCK_LENGTH - padlen ) + diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + else + bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + } + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + if( ret != 0 ) + { + goto cleanup; + } + memset( output + Plen, 0, padlen ); + *out_len = Plen; + } + else + { + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + +cleanup: + if( ret != 0 ) + { + memset( output, 0, *out_len ); + *out_len = 0; + } + + mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); + mbedtls_platform_zeroize( &diff, sizeof( diff ) ); + mbedtls_platform_zeroize( A, sizeof( A ) ); + + return( ret ); +} + +#endif /* !MBEDTLS_NIST_KW_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#define KW_TESTS 3 + +/* + * Test vectors taken from NIST + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW + */ +static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; + +static const unsigned char kw_key[KW_TESTS][32] = { + { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, + 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, + { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, + 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, + 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, + { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, + 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, + 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, + 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } +}; + +static const unsigned char kw_msg[KW_TESTS][40] = { + { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, + 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, + { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, + 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, + 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, + 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, + 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, + { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, + 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, + 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } +}; + +static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; +static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; +static const unsigned char kw_res[KW_TESTS][48] = { + { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, + 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, + 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, + { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, + 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, + 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, + 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, + 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, + 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, + { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, + 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, + 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, + 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } +}; + +static const unsigned char kwp_key[KW_TESTS][32] = { + { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, + 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, + { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, + 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, + 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, + { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, + 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, + 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, + 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } +}; + +static const unsigned char kwp_msg[KW_TESTS][31] = { + { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, + 0x96 }, + { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, + 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, + 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, + 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, + { 0xd1 } +}; +static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; + +static const unsigned char kwp_res[KW_TESTS][48] = { + { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, + 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, + 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, + { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, + 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, + 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, + 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, + 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, + { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, + 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } +}; +static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; + +int mbedtls_nist_kw_self_test( int verbose ) +{ + mbedtls_nist_kw_context ctx; + unsigned char out[48]; + size_t olen; + int i; + int ret = 0; + mbedtls_nist_kw_init( &ctx ); + + for( i = 0; i < KW_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed " ); + + goto end; + } + + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], + kw_msg_len[i], out, &olen, sizeof( out ) ); + if( ret != 0 || kw_out_len[i] != olen || + memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, + out, olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kw_msg_len[i] || + memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } + + for( i = 0; i < KW_TESTS; i++ ) + { + olen = sizeof( out ); + if( verbose != 0 ) + mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], + key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed " ); + + goto end; + } + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], + kwp_msg_len[i], out, &olen, sizeof( out ) ); + + if( ret != 0 || kwp_out_len[i] != olen || + memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kwp_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, + olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kwp_msg_len[i] || + memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } +end: + mbedtls_nist_kw_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_NIST_KW_C */ diff --git a/Externals/mbedtls/library/oid.c b/Externals/mbedtls/library/oid.c index f13826ed74..edea950f8f 100644 --- a/Externals/mbedtls/library/oid.c +++ b/Externals/mbedtls/library/oid.c @@ -625,6 +625,51 @@ static const oid_md_alg_t oid_md_alg[] = FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_PKCS12_C) diff --git a/Externals/mbedtls/library/pem.c b/Externals/mbedtls/library/pem.c index 1ee3966e1e..897c8a0d6f 100644 --- a/Externals/mbedtls/library/pem.c +++ b/Externals/mbedtls/library/pem.c @@ -33,6 +33,7 @@ #include "mbedtls/aes.h" #include "mbedtls/md5.h" #include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" #include @@ -44,11 +45,6 @@ #define mbedtls_free free #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - #if defined(MBEDTLS_PEM_PARSE_C) void mbedtls_pem_init( mbedtls_pem_context *ctx ) { @@ -82,31 +78,33 @@ static int pem_get_iv( const unsigned char *s, unsigned char *iv, return( 0 ); } -static void pem_pbkdf1( unsigned char *key, size_t keylen, - unsigned char *iv, - const unsigned char *pwd, size_t pwdlen ) +static int pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) { mbedtls_md5_context md5_ctx; unsigned char md5sum[16]; size_t use_len; + int ret; mbedtls_md5_init( &md5_ctx ); /* * key[ 0..15] = MD5(pwd || IV) */ - mbedtls_md5_starts( &md5_ctx ); - mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); - mbedtls_md5_update( &md5_ctx, iv, 8 ); - mbedtls_md5_finish( &md5_ctx, md5sum ); + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; if( keylen <= 16 ) { memcpy( key, md5sum, keylen ); - - mbedtls_md5_free( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); - return; + goto exit; } memcpy( key, md5sum, 16 ); @@ -114,11 +112,16 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen, /* * key[16..23] = MD5(key[ 0..15] || pwd || IV]) */ - mbedtls_md5_starts( &md5_ctx ); - mbedtls_md5_update( &md5_ctx, md5sum, 16 ); - mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); - mbedtls_md5_update( &md5_ctx, iv, 8 ); - mbedtls_md5_finish( &md5_ctx, md5sum ); + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; use_len = 16; if( keylen < 32 ) @@ -126,53 +129,68 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen, memcpy( key + 16, md5sum, use_len ); +exit: mbedtls_md5_free( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); + mbedtls_platform_zeroize( md5sum, 16 ); + + return( ret ); } #if defined(MBEDTLS_DES_C) /* * Decrypt with DES-CBC, using PBKDF1 for key derivation */ -static void pem_des_decrypt( unsigned char des_iv[8], - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) +static int pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) { mbedtls_des_context des_ctx; unsigned char des_key[8]; + int ret; mbedtls_des_init( &des_ctx ); - pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; - mbedtls_des_setkey_dec( &des_ctx, des_key ); - mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, des_iv, buf, buf ); +exit: mbedtls_des_free( &des_ctx ); - mbedtls_zeroize( des_key, 8 ); + mbedtls_platform_zeroize( des_key, 8 ); + + return( ret ); } /* * Decrypt with 3DES-CBC, using PBKDF1 for key derivation */ -static void pem_des3_decrypt( unsigned char des3_iv[8], - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) +static int pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) { mbedtls_des3_context des3_ctx; unsigned char des3_key[24]; + int ret; mbedtls_des3_init( &des3_ctx ); - pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; - mbedtls_des3_set3key_dec( &des3_ctx, des3_key ); - mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, des3_iv, buf, buf ); +exit: mbedtls_des3_free( &des3_ctx ); - mbedtls_zeroize( des3_key, 24 ); + mbedtls_platform_zeroize( des3_key, 24 ); + + return( ret ); } #endif /* MBEDTLS_DES_C */ @@ -180,23 +198,29 @@ static void pem_des3_decrypt( unsigned char des3_iv[8], /* * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation */ -static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) +static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) { mbedtls_aes_context aes_ctx; unsigned char aes_key[32]; + int ret; mbedtls_aes_init( &aes_ctx ); - pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; - mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); - mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, aes_iv, buf, buf ); +exit: mbedtls_aes_free( &aes_ctx ); - mbedtls_zeroize( aes_key, keylen ); + mbedtls_platform_zeroize( aes_key, keylen ); + + return( ret ); } #endif /* MBEDTLS_AES_C */ @@ -249,7 +273,7 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const enc = 0; - if( memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) { #if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) @@ -262,22 +286,22 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const #if defined(MBEDTLS_DES_C) - if( memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) { enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; s1 += 23; - if( pem_get_iv( s1, pem_iv, 8 ) != 0 ) + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); s1 += 16; } - else if( memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) { enc_alg = MBEDTLS_CIPHER_DES_CBC; s1 += 18; - if( pem_get_iv( s1, pem_iv, 8) != 0 ) + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); s1 += 16; @@ -285,9 +309,11 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) - if( memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) { - if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) enc_alg = MBEDTLS_CIPHER_AES_128_CBC; else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) enc_alg = MBEDTLS_CIPHER_AES_192_CBC; @@ -297,7 +323,7 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); s1 += 22; - if( pem_get_iv( s1, pem_iv, 16 ) != 0 ) + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); s1 += 32; @@ -316,7 +342,7 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ } - if( s1 == s2 ) + if( s1 >= s2 ) return( MBEDTLS_ERR_PEM_INVALID_DATA ); ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); @@ -329,6 +355,7 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) { + mbedtls_platform_zeroize( buf, len ); mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); } @@ -339,38 +366,49 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) if( pwd == NULL ) { + mbedtls_platform_zeroize( buf, len ); mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); } + ret = 0; + #if defined(MBEDTLS_DES_C) if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) - pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) - pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); + ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) - pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) - pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) - pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); #endif /* MBEDTLS_AES_C */ + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } + /* * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 * length bytes (allow 4 to be sure) in all known use cases. * - * Use that as heurisitic to try detecting password mismatchs. + * Use that as a heuristic to try to detect password mismatches. */ if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) { + mbedtls_platform_zeroize( buf, len ); mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); } #else + mbedtls_platform_zeroize( buf, len ); mbedtls_free( buf ); return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && @@ -385,10 +423,14 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const void mbedtls_pem_free( mbedtls_pem_context *ctx ) { - mbedtls_free( ctx->buf ); + if ( ctx->buf != NULL ) + { + mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); + mbedtls_free( ctx->buf ); + } mbedtls_free( ctx->info ); - mbedtls_zeroize( ctx, sizeof( mbedtls_pem_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); } #endif /* MBEDTLS_PEM_PARSE_C */ @@ -398,7 +440,7 @@ int mbedtls_pem_write_buffer( const char *header, const char *footer, unsigned char *buf, size_t buf_len, size_t *olen ) { int ret; - unsigned char *encode_buf, *c, *p = buf; + unsigned char *encode_buf = NULL, *c, *p = buf; size_t len = 0, use_len, add_len = 0; mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); @@ -410,7 +452,8 @@ int mbedtls_pem_write_buffer( const char *header, const char *footer, return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); } - if( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) + if( use_len != 0 && + ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, diff --git a/Externals/mbedtls/library/pk.c b/Externals/mbedtls/library/pk.c index 10bd0a5828..bac685dc19 100644 --- a/Externals/mbedtls/library/pk.c +++ b/Externals/mbedtls/library/pk.c @@ -29,6 +29,8 @@ #include "mbedtls/pk.h" #include "mbedtls/pk_internal.h" +#include "mbedtls/platform_util.h" + #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif @@ -39,18 +41,21 @@ #include "mbedtls/ecdsa.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +#include +#include + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) /* * Initialise a mbedtls_pk_context */ void mbedtls_pk_init( mbedtls_pk_context *ctx ) { - if( ctx == NULL ) - return; + PK_VALIDATE( ctx != NULL ); ctx->pk_info = NULL; ctx->pk_ctx = NULL; @@ -61,14 +66,44 @@ void mbedtls_pk_init( mbedtls_pk_context *ctx ) */ void mbedtls_pk_free( mbedtls_pk_context *ctx ) { - if( ctx == NULL || ctx->pk_info == NULL ) + if( ctx == NULL ) return; - ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + if ( ctx->pk_info != NULL ) + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL ) + { + return; + } + + ctx->pk_info->rs_free_func( ctx->rs_ctx ); + + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + /* * Get pk_info structure from type */ @@ -100,7 +135,8 @@ const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) */ int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) { - if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) + PK_VALIDATE_RET( ctx != NULL ); + if( info == NULL || ctx->pk_info != NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) @@ -123,7 +159,8 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, mbedtls_rsa_alt_context *rsa_alt; const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; - if( ctx == NULL || ctx->pk_info != NULL ) + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info != NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) @@ -147,7 +184,9 @@ int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, */ int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) { - /* null or NONE context can't do anything */ + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ if( ctx == NULL || ctx->pk_info == NULL ) return( 0 ); @@ -171,6 +210,78 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len return( 0 ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Helper to set up a restart context if needed + */ +static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info ) +{ + /* Don't do anything if already set up or invalid */ + if( ctx == NULL || ctx->pk_info != NULL ) + return( 0 ); + + /* Should never happen when we're called */ + if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Verify a signature (restartable) + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->verify_rs_func != NULL ) + { + int ret; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + /* * Verify a signature */ @@ -178,15 +289,8 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ) { - if( ctx == NULL || ctx->pk_info == NULL || - pk_hashlen_helper( md_alg, &hash_len ) != 0 ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->verify_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len ) ); + return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, NULL ) ); } /* @@ -197,7 +301,12 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ) { - if( ctx == NULL || ctx->pk_info == NULL ) + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ! mbedtls_pk_can_do( ctx, type ) ) @@ -209,6 +318,11 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, int ret; const mbedtls_pk_rsassa_pss_options *pss_opts; +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + if( options == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -232,7 +346,7 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, return( 0 ); #else return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); -#endif +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ } /* General case: no options */ @@ -242,6 +356,55 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); } +/* + * Make a signature (restartable) + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->sign_rs_func != NULL ) + { + int ret; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + /* * Make a signature */ @@ -250,15 +413,8 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - if( ctx == NULL || ctx->pk_info == NULL || - pk_hashlen_helper( md_alg, &hash_len ) != 0 ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->sign_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len, f_rng, p_rng ) ); + return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng, NULL ) ); } /* @@ -269,7 +425,12 @@ int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - if( ctx == NULL || ctx->pk_info == NULL ) + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ctx->pk_info->decrypt_func == NULL ) @@ -287,7 +448,12 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - if( ctx == NULL || ctx->pk_info == NULL ) + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ctx->pk_info->encrypt_func == NULL ) @@ -302,8 +468,11 @@ int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, */ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) { - if( pub == NULL || pub->pk_info == NULL || - prv == NULL || prv->pk_info == NULL || + PK_VALIDATE_RET( pub != NULL ); + PK_VALIDATE_RET( prv != NULL ); + + if( pub->pk_info == NULL || + prv->pk_info == NULL || prv->pk_info->check_pair_func == NULL ) { return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -328,6 +497,8 @@ int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_conte */ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) { + /* For backward compatibility, accept NULL or a context that + * isn't set up yet, and return a fake value that should be safe. */ if( ctx == NULL || ctx->pk_info == NULL ) return( 0 ); @@ -339,7 +510,8 @@ size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) */ int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) { - if( ctx == NULL || ctx->pk_info == NULL ) + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); if( ctx->pk_info->debug_func == NULL ) diff --git a/Externals/mbedtls/library/pk_wrap.c b/Externals/mbedtls/library/pk_wrap.c index 712ad48323..87806be337 100644 --- a/Externals/mbedtls/library/pk_wrap.c +++ b/Externals/mbedtls/library/pk_wrap.c @@ -41,6 +41,10 @@ #include "mbedtls/ecdsa.h" #endif +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +#include "mbedtls/platform_util.h" +#endif + #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else @@ -49,12 +53,8 @@ #define mbedtls_free free #endif -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} -#endif +#include +#include #if defined(MBEDTLS_RSA_C) static int rsa_can_do( mbedtls_pk_type_t type ) @@ -65,7 +65,8 @@ static int rsa_can_do( mbedtls_pk_type_t type ) static size_t rsa_get_bitlen( const void *ctx ) { - return( 8 * ((const mbedtls_rsa_context *) ctx)->len ); + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); } static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, @@ -73,16 +74,28 @@ static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, const unsigned char *sig, size_t sig_len ) { int ret; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); - if( sig_len < ((mbedtls_rsa_context *) ctx)->len ) +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - if( ( ret = mbedtls_rsa_pkcs1_verify( (mbedtls_rsa_context *) ctx, NULL, NULL, + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, md_alg, (unsigned int) hash_len, hash, sig ) ) != 0 ) return( ret ); - if( sig_len > ((mbedtls_rsa_context *) ctx)->len ) + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if( sig_len > rsa_len ) return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); return( 0 ); @@ -93,9 +106,16 @@ static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - *sig_len = ((mbedtls_rsa_context *) ctx)->len; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; - return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, md_alg, (unsigned int) hash_len, hash, sig ) ); } @@ -104,10 +124,12 @@ static int rsa_decrypt_wrap( void *ctx, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - if( ilen != ((mbedtls_rsa_context *) ctx)->len ) + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, f_rng, p_rng, + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); } @@ -116,13 +138,14 @@ static int rsa_encrypt_wrap( void *ctx, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - *olen = ((mbedtls_rsa_context *) ctx)->len; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); if( *olen > osize ) return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); - return( mbedtls_rsa_pkcs1_encrypt( (mbedtls_rsa_context *) ctx, - f_rng, p_rng, MBEDTLS_RSA_PUBLIC, ilen, input, output ) ); + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + ilen, input, output ) ); } static int rsa_check_pair_wrap( const void *pub, const void *prv ) @@ -167,11 +190,19 @@ const mbedtls_pk_info_t mbedtls_rsa_info = { rsa_can_do, rsa_verify_wrap, rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_decrypt_wrap, rsa_encrypt_wrap, rsa_check_pair_wrap, rsa_alloc_wrap, rsa_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_debug, }; #endif /* MBEDTLS_RSA_C */ @@ -239,6 +270,110 @@ static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, return( ret ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); + +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + eckey_restart_ctx *rs_ctx; + + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); +} + +static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} + +static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + int ret; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDSA_C */ static int eckey_check_pair( const void *pub, const void *prv ) @@ -278,15 +413,23 @@ const mbedtls_pk_info_t mbedtls_eckey_info = { #if defined(MBEDTLS_ECDSA_C) eckey_verify_wrap, eckey_sign_wrap, -#else - NULL, - NULL, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, #endif +#else /* MBEDTLS_ECDSA_C */ + NULL, + NULL, +#endif /* MBEDTLS_ECDSA_C */ NULL, NULL, eckey_check_pair, eckey_alloc_wrap, eckey_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif eckey_debug, }; @@ -306,11 +449,19 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = { eckeydh_can_do, NULL, NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif NULL, NULL, eckey_check_pair, eckey_alloc_wrap, /* Same underlying key structure */ eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif eckey_debug, /* Same underlying key structure */ }; #endif /* MBEDTLS_ECP_C */ @@ -346,6 +497,40 @@ static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); + +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + static void *ecdsa_alloc_wrap( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); @@ -362,6 +547,24 @@ static void ecdsa_free_wrap( void *ctx ) mbedtls_free( ctx ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void ecdsa_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + const mbedtls_pk_info_t mbedtls_ecdsa_info = { MBEDTLS_PK_ECDSA, "ECDSA", @@ -369,11 +572,19 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = { ecdsa_can_do, ecdsa_verify_wrap, ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif NULL, NULL, eckey_check_pair, /* Compatible key structures */ ecdsa_alloc_wrap, ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif eckey_debug, /* Compatible key structures */ }; #endif /* MBEDTLS_ECDSA_C */ @@ -402,6 +613,11 @@ static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, { mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, @@ -467,7 +683,7 @@ static void *rsa_alt_alloc_wrap( void ) static void rsa_alt_free_wrap( void *ctx ) { - mbedtls_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); mbedtls_free( ctx ); } @@ -478,6 +694,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { rsa_alt_can_do, NULL, rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_alt_decrypt_wrap, NULL, #if defined(MBEDTLS_RSA_C) @@ -487,6 +707,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { #endif rsa_alt_alloc_wrap, rsa_alt_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif NULL, }; diff --git a/Externals/mbedtls/library/pkcs12.c b/Externals/mbedtls/library/pkcs12.c index c603a13577..7edf064c13 100644 --- a/Externals/mbedtls/library/pkcs12.c +++ b/Externals/mbedtls/library/pkcs12.c @@ -36,6 +36,7 @@ #include "mbedtls/pkcs12.h" #include "mbedtls/asn1.h" #include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" #include @@ -47,10 +48,7 @@ #include "mbedtls/des.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +#if defined(MBEDTLS_ASN1_PARSE_C) static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations ) @@ -166,7 +164,7 @@ int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, goto exit; exit: - mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); mbedtls_arc4_free( &ctx ); return( ret ); @@ -223,13 +221,15 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; exit: - mbedtls_zeroize( key, sizeof( key ) ); - mbedtls_zeroize( iv, sizeof( iv ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( iv, sizeof( iv ) ); mbedtls_cipher_free( &cipher_ctx ); return( ret ); } +#endif /* MBEDTLS_ASN1_PARSE_C */ + static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, const unsigned char *filler, size_t fill_len ) { @@ -352,10 +352,10 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, ret = 0; exit: - mbedtls_zeroize( salt_block, sizeof( salt_block ) ); - mbedtls_zeroize( pwd_block, sizeof( pwd_block ) ); - mbedtls_zeroize( hash_block, sizeof( hash_block ) ); - mbedtls_zeroize( hash_output, sizeof( hash_output ) ); + mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); mbedtls_md_free( &md_ctx ); diff --git a/Externals/mbedtls/library/pkcs5.c b/Externals/mbedtls/library/pkcs5.c index e28d5a8473..50133435ce 100644 --- a/Externals/mbedtls/library/pkcs5.c +++ b/Externals/mbedtls/library/pkcs5.c @@ -38,9 +38,12 @@ #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #include "mbedtls/cipher.h" #include "mbedtls/oid.h" +#endif /* MBEDTLS_ASN1_PARSE_C */ #include @@ -51,6 +54,7 @@ #define mbedtls_printf printf #endif +#if defined(MBEDTLS_ASN1_PARSE_C) static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations, int *keylen, mbedtls_md_type_t *md_type ) @@ -96,11 +100,9 @@ static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - if( MBEDTLS_OID_CMP( MBEDTLS_OID_HMAC_SHA1, &prf_alg_oid ) != 0 ) + if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - *md_type = MBEDTLS_MD_SHA1; - if( p != end ) return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); @@ -213,6 +215,7 @@ exit: return( ret ); } +#endif /* MBEDTLS_ASN1_PARSE_C */ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, @@ -231,8 +234,10 @@ int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *p memset( counter, 0, 4 ); counter[3] = 1; +#if UINT_MAX > 0xFFFFFFFF if( iteration_count > 0xFFFFFFFF ) return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif while( key_length ) { diff --git a/Externals/mbedtls/library/pkparse.c b/Externals/mbedtls/library/pkparse.c index 275429e603..ae210bca6a 100644 --- a/Externals/mbedtls/library/pkparse.c +++ b/Externals/mbedtls/library/pkparse.c @@ -30,6 +30,7 @@ #include "mbedtls/pk.h" #include "mbedtls/asn1.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include @@ -60,12 +61,13 @@ #define mbedtls_free free #endif -#if defined(MBEDTLS_FS_IO) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) +#if defined(MBEDTLS_FS_IO) /* * Load all data from a file into a given buffer. * @@ -78,6 +80,10 @@ int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) FILE *f; long size; + PK_VALIDATE_RET( path != NULL ); + PK_VALIDATE_RET( buf != NULL ); + PK_VALIDATE_RET( n != NULL ); + if( ( f = fopen( path, "rb" ) ) == NULL ) return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); @@ -101,7 +107,10 @@ int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) if( fread( *buf, 1, *n, f ) != *n ) { fclose( f ); + + mbedtls_platform_zeroize( *buf, *n ); mbedtls_free( *buf ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); } @@ -125,6 +134,9 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, size_t n; unsigned char *buf; + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) return( ret ); @@ -134,7 +146,7 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, ret = mbedtls_pk_parse_key( ctx, buf, n, (const unsigned char *) pwd, strlen( pwd ) ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -149,12 +161,15 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) size_t n; unsigned char *buf; + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) return( ret ); ret = mbedtls_pk_parse_public_key( ctx, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -175,6 +190,10 @@ static int pk_get_ecparams( unsigned char **p, const unsigned char *end, { int ret; + if ( end - *p < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + /* Tag may be either OID or SEQUENCE */ params->tag = **p; if( params->tag != MBEDTLS_ASN1_OID @@ -520,19 +539,36 @@ static int pk_get_rsapubkey( unsigned char **p, return( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + if( *p != end ) return( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); - - rsa->len = mbedtls_mpi_size( &rsa->N ); - return( 0 ); } #endif /* MBEDTLS_RSA_C */ @@ -585,6 +621,11 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; const mbedtls_pk_info_t *pk_info; + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( end != NULL ); + PK_VALIDATE_RET( pk != NULL ); + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { @@ -643,10 +684,13 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen ) { - int ret; + int ret, version; size_t len; unsigned char *p, *end; + mbedtls_mpi T; + mbedtls_mpi_init( &T ); + p = (unsigned char *) key; end = p + keylen; @@ -674,45 +718,88 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, end = p + len; - if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) { return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); } - if( rsa->ver != 0 ) + if( version != 0 ) { return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); } - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) - { - mbedtls_rsa_free( rsa ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; - rsa->len = mbedtls_mpi_size( &rsa->N ); + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, p, len ) ) != 0 ) + goto cleanup; + p += len; + + /* Import D */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + p, len, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import P */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import Q */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Complete the RSA private key */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ) + goto cleanup; + + /* Check optional parameters */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; if( p != end ) { - mbedtls_rsa_free( rsa ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ; } - if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 ) +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret; + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + mbedtls_rsa_free( rsa ); - return( ret ); } - return( 0 ); + return( ret ); } #endif /* MBEDTLS_RSA_C */ @@ -788,7 +875,10 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, mbedtls_ecp_keypair_free( eck ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); } + } + if( p != end ) + { /* * Is 'publickey' present? If not, or if we can't read it (eg because it * is compressed), create it from the private key. @@ -844,6 +934,16 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, /* * Parse an unencrypted PKCS#8 encoded private key + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * */ static int pk_parse_key_pkcs8_unencrypted_der( mbedtls_pk_context *pk, @@ -859,7 +959,7 @@ static int pk_parse_key_pkcs8_unencrypted_der( const mbedtls_pk_info_t *pk_info; /* - * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) * * PrivateKeyInfo ::= SEQUENCE { * version Version, @@ -932,16 +1032,22 @@ static int pk_parse_key_pkcs8_unencrypted_der( /* * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) static int pk_parse_key_pkcs8_encrypted_der( mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, + unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ) { int ret, decrypted = 0; size_t len; - unsigned char buf[2048]; + unsigned char *buf; unsigned char *p, *end; mbedtls_asn1_buf pbe_alg_oid, pbe_params; #if defined(MBEDTLS_PKCS12_C) @@ -949,16 +1055,14 @@ static int pk_parse_key_pkcs8_encrypted_der( mbedtls_md_type_t md_alg; #endif - memset( buf, 0, sizeof( buf ) ); - - p = (unsigned char *) key; + p = key; end = p + keylen; if( pwdlen == 0 ) return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); /* - * This function parses the EncryptedPrivatKeyInfo object (PKCS#8) + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) * * EncryptedPrivateKeyInfo ::= SEQUENCE { * encryptionAlgorithm EncryptionAlgorithmIdentifier, @@ -970,6 +1074,7 @@ static int pk_parse_key_pkcs8_encrypted_der( * EncryptedData ::= OCTET STRING * * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * */ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) @@ -985,11 +1090,10 @@ static int pk_parse_key_pkcs8_encrypted_der( if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - if( len > sizeof( buf ) ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + buf = p; /* - * Decrypt EncryptedData with appropriate PDE + * Decrypt EncryptedData with appropriate PBE */ #if defined(MBEDTLS_PKCS12_C) if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) @@ -1062,16 +1166,22 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, { int ret; const mbedtls_pk_info_t *pk_info; - #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; +#endif - mbedtls_pem_init( &pem ); + PK_VALIDATE_RET( pk != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1081,10 +1191,8 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, if( ret == 0 ) { - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), pem.buf, pem.buflen ) ) != 0 ) { @@ -1104,7 +1212,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, #if defined(MBEDTLS_ECP_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1113,10 +1221,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, key, pwd, pwdlen, &len ); if( ret == 0 ) { - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), pem.buf, pem.buflen ) ) != 0 ) { @@ -1135,7 +1242,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, #endif /* MBEDTLS_ECP_C */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1158,7 +1265,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1181,26 +1288,38 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, return( ret ); #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ #else - ((void) ret); ((void) pwd); ((void) pwdlen); #endif /* MBEDTLS_PEM_PARSE_C */ /* - * At this point we only know it's not a PEM formatted key. Could be any - * of the known DER encoded private key formats - * - * We try the different DER format parsers to see if one passes without - * error - */ + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, - pwd, pwdlen ) ) == 0 ) { - return( 0 ); + unsigned char *key_copy; + + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen ); + + mbedtls_platform_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); } + if( ret == 0 ) + return( 0 ); + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) { @@ -1212,33 +1331,42 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, return( 0 ); mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); #if defined(MBEDTLS_RSA_C) - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 ) + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) { return( 0 ); } mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 ) + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) == 0 ) { return( 0 ); } - mbedtls_pk_free( pk ); #endif /* MBEDTLS_ECP_C */ + /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); } @@ -1250,14 +1378,55 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, { int ret; unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; +#endif + PK_VALIDATE_RET( ctx != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL || keylen == 0 ); + +#if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init( &pem ); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) + if( key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, @@ -1270,23 +1439,43 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, /* * Was PEM encoded */ - key = pem.buf; - keylen = pem.buflen; + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); } else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) { mbedtls_pem_free( &pem ); return( ret ); } + mbedtls_pem_free( &pem ); #endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ p = (unsigned char *) key; ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_free( &pem ); -#endif - return( ret ); } diff --git a/Externals/mbedtls/library/pkwrite.c b/Externals/mbedtls/library/pkwrite.c index 83b798c119..8d1da2f757 100644 --- a/Externals/mbedtls/library/pkwrite.c +++ b/Externals/mbedtls/library/pkwrite.c @@ -30,6 +30,7 @@ #include "mbedtls/pk.h" #include "mbedtls/asn1write.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include @@ -54,6 +55,12 @@ #define mbedtls_free free #endif +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + #if defined(MBEDTLS_RSA_C) /* * RSAPublicKey ::= SEQUENCE { @@ -62,13 +69,31 @@ * } */ static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, - mbedtls_rsa_context *rsa ) + mbedtls_rsa_context *rsa ) { int ret; size_t len = 0; + mbedtls_mpi T; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->E ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->N ) ); + mbedtls_mpi_init( &T ); + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + +end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | @@ -83,7 +108,7 @@ static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, * EC public key is an EC point */ static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec ) + mbedtls_ecp_keypair *ec ) { int ret; size_t len = 0; @@ -111,7 +136,7 @@ static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, * } */ static int pk_write_ec_param( unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec ) + mbedtls_ecp_keypair *ec ) { int ret; size_t len = 0; @@ -128,11 +153,16 @@ static int pk_write_ec_param( unsigned char **p, unsigned char *start, #endif /* MBEDTLS_ECP_C */ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key ) + const mbedtls_pk_context *key ) { int ret; size_t len = 0; + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( start != NULL ); + PK_VALIDATE_RET( key != NULL ); + #if defined(MBEDTLS_RSA_C) if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); @@ -155,6 +185,11 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si size_t len = 0, par_len = 0, oid_len; const char *oid; + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + c = buf + size; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); @@ -199,27 +234,92 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) { int ret; - unsigned char *c = buf + size; + unsigned char *c; size_t len = 0; + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + #if defined(MBEDTLS_RSA_C) if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) { + mbedtls_mpi T; /* Temporary holding the exported parameters */ mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + mbedtls_mpi_init( &T ); + + /* Export QP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DQ */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export Q */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export P */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export D */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, + buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); } else #endif /* MBEDTLS_RSA_C */ @@ -381,6 +481,9 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, si unsigned char output_buf[PUB_DER_MAX_BYTES]; size_t olen = 0; + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) { @@ -404,6 +507,9 @@ int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_ const char *begin, *end; size_t olen = 0; + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) return( ret ); diff --git a/Externals/mbedtls/library/platform.c b/Externals/mbedtls/library/platform.c index 2591c45d75..73a6db9ebe 100644 --- a/Externals/mbedtls/library/platform.c +++ b/Externals/mbedtls/library/platform.c @@ -28,8 +28,16 @@ #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +/* The compile time configuration of memory allocation via the macros + * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime + * configuration via mbedtls_platform_set_calloc_free(). So, omit everything + * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ +#if defined(MBEDTLS_PLATFORM_MEMORY) && \ + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) -#if defined(MBEDTLS_PLATFORM_MEMORY) #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) static void *platform_calloc_uninit( size_t n, size_t size ) { @@ -50,17 +58,29 @@ static void platform_free_uninit( void *ptr ) #define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit #endif /* !MBEDTLS_PLATFORM_STD_FREE */ -void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; -void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), void (*free_func)( void * ) ) { - mbedtls_calloc = calloc_func; - mbedtls_free = free_func; + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; return( 0 ); } -#endif /* MBEDTLS_PLATFORM_MEMORY */ +#endif /* MBEDTLS_PLATFORM_MEMORY && + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ #if defined(_WIN32) #include @@ -74,7 +94,7 @@ int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) return( -1 ); va_start( argp, fmt ); -#if defined(_TRUNCATE) +#if defined(_TRUNCATE) && !defined(__MINGW32__) ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); #else ret = _vsnprintf( s, n, fmt, argp ); @@ -228,16 +248,17 @@ int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) size_t n; if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) - return -1; + return( -1 ); if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) { fclose( file ); - return -1; + mbedtls_platform_zeroize( buf, buf_len ); + return( -1 ); } fclose( file ); - return( n ); + return( (int)n ); } int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) @@ -255,7 +276,7 @@ int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) } fclose( file ); - return( n ); + return( (int)n ); } #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ @@ -304,4 +325,24 @@ int mbedtls_platform_set_nv_seed( #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + #endif /* MBEDTLS_PLATFORM_C */ diff --git a/Externals/mbedtls/library/platform_util.c b/Externals/mbedtls/library/platform_util.c new file mode 100644 index 0000000000..756e22679a --- /dev/null +++ b/Externals/mbedtls/library/platform_util.c @@ -0,0 +1,136 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * Copyright (C) 2018, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" +#include "mbedtls/threading.h" + +#include +#include + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + memset_func( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_r( tt, tm_buf ) ); +#else + struct tm *lt; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + lt = gmtime( tt ); + + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ diff --git a/Externals/mbedtls/library/poly1305.c b/Externals/mbedtls/library/poly1305.c new file mode 100644 index 0000000000..b274119181 --- /dev/null +++ b/Externals/mbedtls/library/poly1305.c @@ -0,0 +1,559 @@ +/** + * \file poly1305.c + * + * \brief Poly1305 authentication algorithm. + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_POLY1305_C) + +#include "mbedtls/poly1305.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_POLY1305_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define POLY1305_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define POLY1305_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define POLY1305_BLOCK_SIZE_BYTES ( 16U ) + +#define BYTES_TO_U32_LE( data, offset ) \ + ( (uint32_t) data[offset] \ + | (uint32_t) ( (uint32_t) data[( offset ) + 1] << 8 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 2] << 16 ) \ + | (uint32_t) ( (uint32_t) data[( offset ) + 3] << 24 ) \ + ) + +/* + * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. + * However we provided an alternative for platforms without such a multiplier. + */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) +static uint64_t mul64( uint32_t a, uint32_t b ) +{ + /* a = al + 2**16 ah, b = bl + 2**16 bh */ + const uint16_t al = (uint16_t) a; + const uint16_t bl = (uint16_t) b; + const uint16_t ah = a >> 16; + const uint16_t bh = b >> 16; + + /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ + const uint32_t lo = (uint32_t) al * bl; + const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh; + const uint32_t hi = (uint32_t) ah * bh; + + return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) ); +} +#else +static inline uint64_t mul64( uint32_t a, uint32_t b ) +{ + return( (uint64_t) a * b ); +} +#endif + + +/** + * \brief Process blocks with Poly1305. + * + * \param ctx The Poly1305 context. + * \param nblocks Number of blocks to process. Note that this + * function only processes full blocks. + * \param input Buffer containing the input block(s). + * \param needs_padding Set to 0 if the padding bit has already been + * applied to the input data before calling this + * function. Otherwise, set this parameter to 1. + */ +static void poly1305_process( mbedtls_poly1305_context *ctx, + size_t nblocks, + const unsigned char *input, + uint32_t needs_padding ) +{ + uint64_t d0, d1, d2, d3; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t r0, r1, r2, r3; + uint32_t rs1, rs2, rs3; + size_t offset = 0U; + size_t i; + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + + rs1 = r1 + ( r1 >> 2U ); + rs2 = r2 + ( r2 >> 2U ); + rs3 = r3 + ( r3 >> 2U ); + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Process full blocks */ + for( i = 0U; i < nblocks; i++ ) + { + /* The input block is treated as a 128-bit little-endian integer */ + d0 = BYTES_TO_U32_LE( input, offset + 0 ); + d1 = BYTES_TO_U32_LE( input, offset + 4 ); + d2 = BYTES_TO_U32_LE( input, offset + 8 ); + d3 = BYTES_TO_U32_LE( input, offset + 12 ); + + /* Compute: acc += (padded) block as a 130-bit integer */ + d0 += (uint64_t) acc0; + d1 += (uint64_t) acc1 + ( d0 >> 32U ); + d2 += (uint64_t) acc2 + ( d1 >> 32U ); + d3 += (uint64_t) acc3 + ( d2 >> 32U ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding; + + /* Compute: acc *= r */ + d0 = mul64( acc0, r0 ) + + mul64( acc1, rs3 ) + + mul64( acc2, rs2 ) + + mul64( acc3, rs1 ); + d1 = mul64( acc0, r1 ) + + mul64( acc1, r0 ) + + mul64( acc2, rs3 ) + + mul64( acc3, rs2 ) + + mul64( acc4, rs1 ); + d2 = mul64( acc0, r2 ) + + mul64( acc1, r1 ) + + mul64( acc2, r0 ) + + mul64( acc3, rs3 ) + + mul64( acc4, rs2 ); + d3 = mul64( acc0, r3 ) + + mul64( acc1, r2 ) + + mul64( acc2, r1 ) + + mul64( acc3, r0 ) + + mul64( acc4, rs3 ); + acc4 *= r0; + + /* Compute: acc %= (2^130 - 5) (partial remainder) */ + d1 += ( d0 >> 32 ); + d2 += ( d1 >> 32 ); + d3 += ( d2 >> 32 ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 = (uint32_t) ( d3 >> 32 ) + acc4; + + d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU ); + acc4 &= 3U; + acc0 = (uint32_t) d0; + d0 = (uint64_t) acc1 + ( d0 >> 32U ); + acc1 = (uint32_t) d0; + d0 = (uint64_t) acc2 + ( d0 >> 32U ); + acc2 = (uint32_t) d0; + d0 = (uint64_t) acc3 + ( d0 >> 32U ); + acc3 = (uint32_t) d0; + d0 = (uint64_t) acc4 + ( d0 >> 32U ); + acc4 = (uint32_t) d0; + + offset += POLY1305_BLOCK_SIZE_BYTES; + } + + ctx->acc[0] = acc0; + ctx->acc[1] = acc1; + ctx->acc[2] = acc2; + ctx->acc[3] = acc3; + ctx->acc[4] = acc4; +} + +/** + * \brief Compute the Poly1305 MAC + * + * \param ctx The Poly1305 context. + * \param mac The buffer to where the MAC is written. Must be + * big enough to contain the 16-byte MAC. + */ +static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + uint64_t d; + uint32_t g0, g1, g2, g3, g4; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t mask; + uint32_t mask_inv; + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. + * We do this by calculating acc - (2^130 - 5), then checking if + * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) + */ + + /* Calculate acc + -(2^130 - 5) */ + d = ( (uint64_t) acc0 + 5U ); + g0 = (uint32_t) d; + d = ( (uint64_t) acc1 + ( d >> 32 ) ); + g1 = (uint32_t) d; + d = ( (uint64_t) acc2 + ( d >> 32 ) ); + g2 = (uint32_t) d; + d = ( (uint64_t) acc3 + ( d >> 32 ) ); + g3 = (uint32_t) d; + g4 = acc4 + (uint32_t) ( d >> 32U ); + + /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ + mask = (uint32_t) 0U - ( g4 >> 2U ); + mask_inv = ~mask; + + /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ + acc0 = ( acc0 & mask_inv ) | ( g0 & mask ); + acc1 = ( acc1 & mask_inv ) | ( g1 & mask ); + acc2 = ( acc2 & mask_inv ) | ( g2 & mask ); + acc3 = ( acc3 & mask_inv ) | ( g3 & mask ); + + /* Add 's' */ + d = (uint64_t) acc0 + ctx->s[0]; + acc0 = (uint32_t) d; + d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U ); + acc1 = (uint32_t) d; + d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U ); + acc2 = (uint32_t) d; + acc3 += ctx->s[3] + (uint32_t) ( d >> 32U ); + + /* Compute MAC (128 least significant bits of the accumulator) */ + mac[ 0] = (unsigned char)( acc0 ); + mac[ 1] = (unsigned char)( acc0 >> 8 ); + mac[ 2] = (unsigned char)( acc0 >> 16 ); + mac[ 3] = (unsigned char)( acc0 >> 24 ); + mac[ 4] = (unsigned char)( acc1 ); + mac[ 5] = (unsigned char)( acc1 >> 8 ); + mac[ 6] = (unsigned char)( acc1 >> 16 ); + mac[ 7] = (unsigned char)( acc1 >> 24 ); + mac[ 8] = (unsigned char)( acc2 ); + mac[ 9] = (unsigned char)( acc2 >> 8 ); + mac[10] = (unsigned char)( acc2 >> 16 ); + mac[11] = (unsigned char)( acc2 >> 24 ); + mac[12] = (unsigned char)( acc3 ); + mac[13] = (unsigned char)( acc3 >> 8 ); + mac[14] = (unsigned char)( acc3 >> 16 ); + mac[15] = (unsigned char)( acc3 >> 24 ); +} + +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) +{ + POLY1305_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( key != NULL ); + + /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = BYTES_TO_U32_LE( key, 0 ) & 0x0FFFFFFFU; + ctx->r[1] = BYTES_TO_U32_LE( key, 4 ) & 0x0FFFFFFCU; + ctx->r[2] = BYTES_TO_U32_LE( key, 8 ) & 0x0FFFFFFCU; + ctx->r[3] = BYTES_TO_U32_LE( key, 12 ) & 0x0FFFFFFCU; + + ctx->s[0] = BYTES_TO_U32_LE( key, 16 ); + ctx->s[1] = BYTES_TO_U32_LE( key, 20 ); + ctx->s[2] = BYTES_TO_U32_LE( key, 24 ); + ctx->s[3] = BYTES_TO_U32_LE( key, 28 ); + + /* Initial accumulator state */ + ctx->acc[0] = 0U; + ctx->acc[1] = 0U; + ctx->acc[2] = 0U; + ctx->acc[3] = 0U; + ctx->acc[4] = 0U; + + /* Queue initially empty */ + mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) ); + ctx->queue_len = 0U; + + return( 0 ); +} + +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + size_t offset = 0U; + size_t remaining = ilen; + size_t queue_free_len; + size_t nblocks; + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) + { + queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + if( ilen < queue_free_len ) + { + /* Not enough data to complete the block. + * Store this data with the other leftovers. + */ + memcpy( &ctx->queue[ctx->queue_len], + input, + ilen ); + + ctx->queue_len += ilen; + + remaining = 0U; + } + else + { + /* Enough data to produce a complete block */ + memcpy( &ctx->queue[ctx->queue_len], + input, + queue_free_len ); + + ctx->queue_len = 0U; + + poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */ + + offset += queue_free_len; + remaining -= queue_free_len; + } + } + + if( remaining >= POLY1305_BLOCK_SIZE_BYTES ) + { + nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; + + poly1305_process( ctx, nblocks, &input[offset], 1U ); + + offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; + remaining %= POLY1305_BLOCK_SIZE_BYTES; + } + + if( remaining > 0U ) + { + /* Store partial block */ + ctx->queue_len = remaining; + memcpy( ctx->queue, &input[offset], remaining ); + } + + return( 0 ); +} + +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + + /* Process any leftover data */ + if( ctx->queue_len > 0U ) + { + /* Add padding bit */ + ctx->queue[ctx->queue_len] = 1U; + ctx->queue_len++; + + /* Pad with zeroes */ + memset( &ctx->queue[ctx->queue_len], + 0, + POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + poly1305_process( ctx, 1U, /* Process 1 block */ + ctx->queue, 0U ); /* Already padded above */ + } + + poly1305_compute_mac( ctx, mac ); + + return( 0 ); +} + +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ) +{ + mbedtls_poly1305_context ctx; + int ret; + POLY1305_VALIDATE_RET( key != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + mbedtls_poly1305_init( &ctx ); + + ret = mbedtls_poly1305_starts( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_update( &ctx, input, ilen ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_finish( &ctx, mac ); + +cleanup: + mbedtls_poly1305_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_POLY1305_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, + 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b + }, + { + 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, + 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 + } +}; + +static const unsigned char test_data[2][127] = +{ + { + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70 + }, + { + 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e + } +}; + +static const size_t test_data_len[2] = +{ + 34U, + 127U +}; + +static const unsigned char test_mac[2][16] = +{ + { + 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 + }, + { + 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 + } +}; + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_poly1305_self_test( int verbose ) +{ + unsigned char mac[16]; + unsigned i; + int ret; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " Poly1305 test %u ", i ); + + ret = mbedtls_poly1305_mac( test_keys[i], + test_data[i], + test_data_len[i], + mac ); + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_POLY1305_C */ diff --git a/Externals/mbedtls/library/ripemd160.c b/Externals/mbedtls/library/ripemd160.c index cdb0a63c0f..bd25ada62c 100644 --- a/Externals/mbedtls/library/ripemd160.c +++ b/Externals/mbedtls/library/ripemd160.c @@ -34,6 +34,7 @@ #if defined(MBEDTLS_RIPEMD160_C) #include "mbedtls/ripemd160.h" +#include "mbedtls/platform_util.h" #include @@ -46,6 +47,8 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ +#if !defined(MBEDTLS_RIPEMD160_ALT) + /* * 32-bit integer manipulation macros (little endian) */ @@ -69,11 +72,6 @@ } #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); @@ -84,7 +82,7 @@ void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); } void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, @@ -96,7 +94,7 @@ void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, /* * RIPEMD-160 context setup */ -void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -106,13 +104,23 @@ void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + mbedtls_ripemd160_starts_ret( ctx ); +} +#endif + #if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) /* * Process one block */ -void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned char data[64] ) +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) { uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; @@ -287,20 +295,32 @@ void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned c ctx->state[3] = ctx->state[4] + A + Bp; ctx->state[4] = ctx->state[0] + B + Cp; ctx->state[0] = C; + + return( 0 ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_ripemd160_process( ctx, data ); +} +#endif #endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ /* * RIPEMD-160 process buffer */ -void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, - const unsigned char *input, size_t ilen ) +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; uint32_t left; if( ilen == 0 ) - return; + return( 0 ); left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -314,7 +334,10 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_ripemd160_process( ctx, ctx->buffer ); + + if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; ilen -= fill; left = 0; @@ -322,7 +345,9 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, while( ilen >= 64 ) { - mbedtls_ripemd160_process( ctx, input ); + if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) + return( ret ); + input += 64; ilen -= 64; } @@ -331,8 +356,19 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, { memcpy( (void *) (ctx->buffer + left), input, ilen ); } + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update_ret( ctx, input, ilen ); +} +#endif + static const unsigned char ripemd160_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -344,8 +380,10 @@ static const unsigned char ripemd160_padding[64] = /* * RIPEMD-160 final digest */ -void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ) +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) { + int ret; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; @@ -360,49 +398,91 @@ void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char out last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - mbedtls_ripemd160_update( ctx, ripemd160_padding, padn ); - mbedtls_ripemd160_update( ctx, msglen, 8 ); + ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 ); + if( ret != 0 ) + return( ret ); PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE( ctx->state[2], output, 8 ); PUT_UINT32_LE( ctx->state[3], output, 12 ); PUT_UINT32_LE( ctx->state[4], output, 16 ); + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + mbedtls_ripemd160_finish_ret( ctx, output ); +} +#endif + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + /* * output = RIPEMD-160( input buffer ) */ -void mbedtls_ripemd160( const unsigned char *input, size_t ilen, - unsigned char output[20] ) +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) { + int ret; mbedtls_ripemd160_context ctx; mbedtls_ripemd160_init( &ctx ); - mbedtls_ripemd160_starts( &ctx ); - mbedtls_ripemd160_update( &ctx, input, ilen ); - mbedtls_ripemd160_finish( &ctx, output ); + + if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: mbedtls_ripemd160_free( &ctx ); + + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_ripemd160_ret( input, ilen, output ); +} +#endif + #if defined(MBEDTLS_SELF_TEST) /* * Test vectors from the RIPEMD-160 paper and * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC */ #define TESTS 8 -#define KEYS 2 -static const char *ripemd160_test_input[TESTS] = +static const unsigned char ripemd160_test_str[TESTS][81] = { - "", - "a", - "abc", - "message digest", - "abcdefghijklmnopqrstuvwxyz", - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" }, +}; + +static const size_t ripemd160_test_strlen[TESTS] = +{ + 0, 1, 3, 14, 26, 56, 62, 80 }; static const unsigned char ripemd160_test_md[TESTS][20] = @@ -430,7 +510,7 @@ static const unsigned char ripemd160_test_md[TESTS][20] = */ int mbedtls_ripemd160_self_test( int verbose ) { - int i; + int i, ret = 0; unsigned char output[20]; memset( output, 0, sizeof output ); @@ -440,16 +520,15 @@ int mbedtls_ripemd160_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); - mbedtls_ripemd160( (const unsigned char *) ripemd160_test_input[i], - strlen( ripemd160_test_input[i] ), - output ); + ret = mbedtls_ripemd160_ret( ripemd160_test_str[i], + ripemd160_test_strlen[i], output ); + if( ret != 0 ) + goto fail; if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); + ret = 1; + goto fail; } if( verbose != 0 ) @@ -460,6 +539,12 @@ int mbedtls_ripemd160_self_test( int verbose ) mbedtls_printf( "\n" ); return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); } #endif /* MBEDTLS_SELF_TEST */ diff --git a/Externals/mbedtls/library/rsa.c b/Externals/mbedtls/library/rsa.c index 40ef2a9480..af1a878599 100644 --- a/Externals/mbedtls/library/rsa.c +++ b/Externals/mbedtls/library/rsa.c @@ -18,6 +18,7 @@ * * This file is part of mbed TLS (https://tls.mbed.org) */ + /* * The following sources were referenced in the design of this implementation * of the RSA algorithm: @@ -29,6 +30,11 @@ * [2] Handbook of Applied Cryptography - 1997, Chapter 8 * Menezes, van Oorschot and Vanstone * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * */ #if !defined(MBEDTLS_CONFIG_FILE) @@ -40,7 +46,9 @@ #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" +#include "mbedtls/rsa_internal.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include @@ -61,6 +69,407 @@ #define mbedtls_free free #endif +#if !defined(MBEDTLS_RSA_ALT) + +/* Parameter validation macros */ +#define RSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) +#define RSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PKCS1_V15) +/* constant-time buffer comparison */ +static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + const unsigned char *A = (const unsigned char *) a; + const unsigned char *B = (const unsigned char *) b; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret; + RSA_VALIDATE_RET( ctx != NULL ); + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + RSA_VALIDATE_RET( ctx != NULL ); + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + int have_N, have_P, have_Q, have_D, have_E; + int n_missing, pq_missing, d_missing, is_pub, is_priv; + + RSA_VALIDATE_RET( ctx != NULL ); + + have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + n_missing = have_P && have_Q && have_D && have_E; + pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + d_missing = have_P && have_Q && !have_D && have_E; + is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif + + return( 0 ); +} + /* * Initialize an RSA context */ @@ -68,6 +477,10 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, int padding, int hash_id ) { + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); mbedtls_rsa_set_padding( ctx, padding, hash_id ); @@ -80,16 +493,34 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, /* * Set padding for an existing RSA context */ -void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ) { + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + ctx->padding = padding; ctx->hash_id = hash_id; } +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + #if defined(MBEDTLS_GENPRIME) /* * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. */ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), @@ -97,64 +528,99 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, unsigned int nbits, int exponent ) { int ret; - mbedtls_mpi P1, Q1, H, G; + mbedtls_mpi H, G, L; + int prime_quality = 0; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( f_rng != NULL ); - if( f_rng == NULL || nbits < 128 || exponent < 3 ) + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - if( nbits % 2 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + /* + * If the modulus is 1024 bit long or shorter, then the security strength of + * the RSA algorithm is less than or equal to 80 bits and therefore an error + * rate of 2^-80 is sufficient. + */ + if( nbits > 1024 ) + prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; - mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); - mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); /* * find primes P and Q with Q < P so that: - * GCD( E, (P-1)*(Q-1) ) == 1 + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) */ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); do { - MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, - f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, + prime_quality, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, - f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, + prime_quality, f_rng, p_rng ) ); - if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) continue; - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); - if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) - continue; + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); - if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) - mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); - } - while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); + + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; + + break; + } + while( 1 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) /* - * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ - ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); cleanup: - mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); if( ret != 0 ) { @@ -172,82 +638,52 @@ cleanup: */ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) { - if( !ctx->N.p || !ctx->E.p ) + RSA_VALIDATE_RET( ctx != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - if( ( ctx->N.p[0] & 1 ) == 0 || - ( ctx->E.p[0] & 1 ) == 0 ) + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } - if( mbedtls_mpi_bitlen( &ctx->N ) < 128 || - mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - if( mbedtls_mpi_bitlen( &ctx->E ) < 2 || + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } return( 0 ); } /* - * Check a private RSA key + * Check for the consistency of all fields in an RSA private key context */ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) { - int ret; - mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; + RSA_VALIDATE_RET( ctx != NULL ); - if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 ) - return( ret ); - - if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); - mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); - mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ ); - mbedtls_mpi_init( &QP ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); - /* - * Check for a valid PKCS1v2 private key - */ - if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || - mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || - mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || - mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || - mbedtls_mpi_cmp_int( &L2, 0 ) != 0 || - mbedtls_mpi_cmp_int( &I, 1 ) != 0 || - mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) { - ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); } -cleanup: - mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); - mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); - mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); - mbedtls_mpi_free( &QP ); + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } - if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) - return( ret ); - - if( ret != 0 ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret ); +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif return( 0 ); } @@ -255,9 +691,13 @@ cleanup: /* * Check if contexts holding a public and private key match */ -int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ) +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) { - if( mbedtls_rsa_check_pubkey( pub ) != 0 || + RSA_VALIDATE_RET( pub != NULL ); + RSA_VALIDATE_RET( prv != NULL ); + + if( mbedtls_rsa_check_pubkey( pub ) != 0 || mbedtls_rsa_check_privkey( prv ) != 0 ) { return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); @@ -282,6 +722,12 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, int ret; size_t olen; mbedtls_mpi T; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_mpi_init( &T ); @@ -356,6 +802,27 @@ cleanup: return( ret ); } +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + /* * Do an RSA private key operation */ @@ -367,19 +834,80 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, { int ret; size_t olen; - mbedtls_mpi T, T1, T2; - /* Make sure we have private key info, prevent possible misuse */ - if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 1 /* private key checks */, + f_rng != NULL /* blinding y/n */ ) != 0 ) + { return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + } #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { @@ -387,6 +915,8 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, goto cleanup; } + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + if( f_rng != NULL ) { /* @@ -396,32 +926,74 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ } #if defined(MBEDTLS_RSA_NO_CRT) - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); #else /* - * faster decryption using the CRT + * Faster decryption using the CRT * - * T1 = input ^ dP mod P - * T2 = input ^ dQ mod Q + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); /* - * T = (T1 - T2) * (Q^-1 mod P) mod P + * T = (TP - TQ) * (Q^-1 mod P) mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); /* - * T = T2 + T * Q + * T = TQ + T * Q */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); #endif /* MBEDTLS_RSA_NO_CRT */ if( f_rng != NULL ) @@ -434,6 +1006,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); } + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + olen = ctx->len; MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); @@ -443,7 +1024,28 @@ cleanup: return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); #endif - mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); if( ret != 0 ) return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); @@ -461,7 +1063,7 @@ cleanup: * \param slen length of the source buffer * \param md_ctx message digest context to use */ -static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen, mbedtls_md_context_t *md_ctx ) { unsigned char mask[MBEDTLS_MD_MAX_SIZE]; @@ -469,6 +1071,7 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, unsigned char *p; unsigned int hlen; size_t i, use_len; + int ret = 0; memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); memset( counter, 0, 4 ); @@ -484,10 +1087,14 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, if( dlen < hlen ) use_len = dlen; - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, src, slen ); - mbedtls_md_update( md_ctx, counter, 4 ); - mbedtls_md_finish( md_ctx, mask ); + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; for( i = 0; i < use_len; ++i ) *p++ ^= mask[i]; @@ -496,6 +1103,11 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, dlen -= use_len; } + +exit: + mbedtls_platform_zeroize( mask, sizeof( mask ) ); + + return( ret ); } #endif /* MBEDTLS_PKCS1_V21 */ @@ -519,6 +1131,13 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -547,7 +1166,8 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, p += hlen; /* Construct DB */ - mbedtls_md( md_info, label, label_len, p ); + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); p += hlen; p += olen - 2 * hlen - 2 - ilen; *p++ = 1; @@ -555,21 +1175,24 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, mbedtls_md_init( &md_ctx ); if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } + goto exit; /* maskedDB: Apply dbMask to DB */ - mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, - &md_ctx ); + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; /* maskedSeed: Apply seedMask to seed */ - mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, - &md_ctx ); + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; +exit: mbedtls_md_free( &md_ctx ); + if( ret != 0 ) + return( ret ); + return( ( mode == MBEDTLS_RSA_PUBLIC ) ? mbedtls_rsa_public( ctx, output, output ) : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); @@ -591,11 +1214,13 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, int ret; unsigned char *p = output; - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); - // We don't check p_rng because it won't be dereferenced here - if( f_rng == NULL || input == NULL || output == NULL ) + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); olen = ctx->len; @@ -609,6 +1234,9 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, *p++ = 0; if( mode == MBEDTLS_RSA_PUBLIC ) { + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + *p++ = MBEDTLS_RSA_CRYPT; while( nb_pad-- > 0 ) @@ -653,6 +1281,12 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output ) { + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + switch( ctx->padding ) { #if defined(MBEDTLS_PKCS1_V15) @@ -695,6 +1329,14 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + /* * Parameters sanity checks */ @@ -724,7 +1366,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); if( ret != 0 ) - return( ret ); + goto cleanup; /* * Unmask data and generate lHash @@ -733,23 +1375,26 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) { mbedtls_md_free( &md_ctx ); - return( ret ); + goto cleanup; } - - /* Generate lHash */ - mbedtls_md( md_info, label, label_len, lhash ); - /* seed: Apply seedMask to maskedSeed */ - mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, - &md_ctx ); - + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || /* DB: Apply dbMask to maskedDB */ - mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, - &md_ctx ); + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } mbedtls_md_free( &md_ctx ); + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + /* * Check contents, in "constant-time" */ @@ -784,19 +1429,121 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, * the different error conditions. */ if( bad != 0 ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } if( ilen - ( p - buf ) > output_max_len ) - return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } *olen = ilen - (p - buf); memcpy( output, p, *olen ); + ret = 0; - return( 0 ); +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) +/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches. + * + * \param value The value to analyze. + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +static unsigned all_or_nothing_int( unsigned value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +/** Check whether a size is out of bounds, without branches. + * + * This is equivalent to `size > max`, but is likely to be compiled to + * to code using bitwise operation rather than a branch. + * + * \param size Size to check. + * \param max Maximum desired value for \p size. + * \return \c 0 if `size <= max`. + * \return \c 1 if `size > max`. + */ +static unsigned size_greater_than( size_t size, size_t max ) +{ + /* Return the sign bit (1 for negative) of (max - size). */ + return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} + +/** Choose between two integer values, without branches. + * + * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param cond Condition to test. + * \param if1 Value to use if \p cond is nonzero. + * \param if0 Value to use if \p cond is zero. + * \return \c if1 if \p cond is nonzero, otherwise \c if0. + */ +static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 ) +{ + unsigned mask = all_or_nothing_int( cond ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} + +/** Shift some data towards the left inside a buffer without leaking + * the length of the data through side channels. + * + * `mem_move_to_left(start, total, offset)` is functionally equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = size_greater_than( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = if_int( no_op, current, next ); + } + buf[total-1] = if_int( no_op, buf[total-1], 0 ); + } +} + /* * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function */ @@ -806,18 +1553,42 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, int mode, size_t *olen, const unsigned char *input, unsigned char *output, - size_t output_max_len) + size_t output_max_len ) { int ret; - size_t ilen, pad_count = 0, i; - unsigned char *p, bad, pad_done = 0; + size_t ilen, i, plaintext_max_size; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + ilen = ctx->len; + plaintext_max_size = ( output_max_len > ilen - 11 ? + ilen - 11 : + output_max_len ); if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - ilen = ctx->len; - if( ilen < 16 || ilen > sizeof( buf ) ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -826,60 +1597,116 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); if( ret != 0 ) - return( ret ); + goto cleanup; - p = buf; - bad = 0; + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= buf[0]; - /* - * Check and get padding len in "constant-time" - */ - bad |= *p++; /* First byte must be 0 */ - - /* This test does not depend on secret data */ if( mode == MBEDTLS_RSA_PRIVATE ) { - bad |= *p++ ^ MBEDTLS_RSA_CRYPT; + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= buf[1] ^ MBEDTLS_RSA_CRYPT; - /* Get padding len, but always read till end of buffer - * (minus one, for the 00 byte) */ - for( i = 0; i < ilen - 3; i++ ) + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) { - pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; + pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1; pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; } - - p += pad_count; - bad |= *p++; /* Must be zero */ } else { - bad |= *p++ ^ MBEDTLS_RSA_SIGN; + /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 + * where PS must be at least 8 bytes with the value 0xFF. */ + bad |= buf[1] ^ MBEDTLS_RSA_SIGN; - /* Get padding len, but always read till end of buffer - * (minus one, for the 00 byte) */ - for( i = 0; i < ilen - 3; i++ ) + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. + * If there's a non-0xff byte in the padding, the padding is bad. */ + for( i = 2; i < ilen; i++ ) { - pad_done |= ( p[i] != 0xFF ); - pad_count += ( pad_done == 0 ); + pad_done |= if_int( buf[i], 0, 1 ); + pad_count += if_int( pad_done, 0, 1 ); + bad |= if_int( pad_done, 0, buf[i] ^ 0xFF ); } - - p += pad_count; - bad |= *p++; /* Must be zero */ } - bad |= ( pad_count < 8 ); + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= if_int( pad_done, 0, 1 ); - if( bad ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + /* There must be at least 8 bytes of padding. */ + bad |= size_greater_than( 8, pad_count ); - if( ilen - ( p - buf ) > output_max_len ) - return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = if_int( bad, + (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = size_greater_than( plaintext_size, + plaintext_max_size ); - return( 0 ); + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = all_or_nothing_int( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + buf[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = if_int( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mem_move_to_left( buf + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros + * into the output buffer. */ + memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); } #endif /* MBEDTLS_PKCS1_V15 */ @@ -894,6 +1721,13 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, unsigned char *output, size_t output_max_len) { + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + switch( ctx->padding ) { #if defined(MBEDTLS_PKCS1_V15) @@ -930,11 +1764,18 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, size_t olen; unsigned char *p = sig; unsigned char salt[MBEDTLS_MD_MAX_SIZE]; - unsigned int slen, hlen, offset = 0; + size_t slen, min_slen, hlen, offset = 0; int ret; size_t msb; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -959,10 +1800,20 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); hlen = mbedtls_md_get_size( md_info ); - slen = hlen; - if( olen < hlen + slen + 2 ) + /* Calculate the largest possible salt length. Normally this is the hash + * length, which is the maximum length the salt can have. If there is not + * enough room, use the maximum salt length that fits. The constraint is + * that the hash length plus the salt length plus 2 bytes must be at most + * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 + * (PKCS#1 v2.2) §9.1.1 step 3. */ + min_slen = hlen - 2; + if( olen < hlen + min_slen + 2 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + else if( olen >= hlen + hlen + 2 ) + slen = hlen; + else + slen = olen - hlen - 2; memset( sig, 0, olen ); @@ -972,33 +1823,35 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; - p += olen - hlen * 2 - 2; + p += olen - hlen - slen - 2; *p++ = 0x01; memcpy( p, salt, slen ); p += slen; mbedtls_md_init( &md_ctx ); if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } + goto exit; /* Generate H = Hash( M' ) */ - mbedtls_md_starts( &md_ctx ); - mbedtls_md_update( &md_ctx, p, 8 ); - mbedtls_md_update( &md_ctx, hash, hashlen ); - mbedtls_md_update( &md_ctx, salt, slen ); - mbedtls_md_finish( &md_ctx, p ); + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; /* Compensate for boundary condition when applying mask */ if( msb % 8 == 0 ) offset = 1; /* maskedDB: Apply dbMask to DB */ - mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); - - mbedtls_md_free( &md_ctx ); + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; sig[0] &= 0xFF >> ( olen * 8 - msb ); @@ -1006,6 +1859,14 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, p += hlen; *p++ = 0xBC; + mbedtls_platform_zeroize( salt, sizeof( salt ) ); + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + return( ( mode == MBEDTLS_RSA_PUBLIC ) ? mbedtls_rsa_public( ctx, sig, sig ) : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); @@ -1016,6 +1877,137 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, /* * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + /* * Do an RSA operation to sign the message digest */ @@ -1028,88 +2020,49 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, const unsigned char *hash, unsigned char *sig ) { - size_t nb_pad, olen, oid_size = 0; - unsigned char *p = sig; - const char *oid = NULL; - unsigned char *sig_try = NULL, *verif = NULL; - size_t i; - unsigned char diff; - volatile unsigned char diff_no_optimize; int ret; + unsigned char *sig_try = NULL, *verif = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - olen = ctx->len; - nb_pad = olen - 3; + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ - if( md_alg != MBEDTLS_MD_NONE ) - { - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - nb_pad -= 10 + oid_size; - - hashlen = mbedtls_md_get_size( md_info ); - } - - nb_pad -= hashlen; - - if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - *p++ = 0; - *p++ = MBEDTLS_RSA_SIGN; - memset( p, 0xFF, nb_pad ); - p += nb_pad; - *p++ = 0; - - if( md_alg == MBEDTLS_MD_NONE ) - { - memcpy( p, hash, hashlen ); - } - else - { - /* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x04 + oid_size ); - *p++ = MBEDTLS_ASN1_OID; - *p++ = oid_size & 0xFF; - memcpy( p, oid, oid_size ); - p += oid_size; - *p++ = MBEDTLS_ASN1_NULL; - *p++ = 0x00; - *p++ = MBEDTLS_ASN1_OCTET_STRING; - *p++ = hashlen; - memcpy( p, hash, hashlen ); - } - - if( mode == MBEDTLS_RSA_PUBLIC ) - return( mbedtls_rsa_public( ctx, sig, sig ) ); + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); /* + * Call respective RSA primitive + */ + + if( mode == MBEDTLS_RSA_PUBLIC ) + { + /* Skip verification on a public key operation */ + return( mbedtls_rsa_public( ctx, sig, sig ) ); + } + + /* Private key operation + * * In order to prevent Lenstra's attack, make the signature in a * temporary buffer and check it before returning it. */ + sig_try = mbedtls_calloc( 1, ctx->len ); if( sig_try == NULL ) return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - verif = mbedtls_calloc( 1, ctx->len ); + verif = mbedtls_calloc( 1, ctx->len ); if( verif == NULL ) { mbedtls_free( sig_try ); @@ -1119,12 +2072,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); - /* Compare in constant time just in case */ - for( diff = 0, i = 0; i < ctx->len; i++ ) - diff |= verif[i] ^ sig[i]; - diff_no_optimize = diff; - - if( diff_no_optimize != 0 ) + if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 ) { ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; goto cleanup; @@ -1152,6 +2100,14 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, const unsigned char *hash, unsigned char *sig ) { + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + switch( ctx->padding ) { #if defined(MBEDTLS_PKCS1_V15) @@ -1189,14 +2145,23 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, int ret; size_t siglen; unsigned char *p; + unsigned char *hash_start; unsigned char result[MBEDTLS_MD_MAX_SIZE]; unsigned char zeros[8]; unsigned int hlen; - size_t slen, msb; + size_t observed_salt_len, msb; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -1232,7 +2197,6 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); hlen = mbedtls_md_get_size( md_info ); - slen = siglen - hlen - 1; /* Currently length of salt + padding */ memset( zeros, 0, 8 ); @@ -1241,61 +2205,77 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, */ msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + /* Compensate for boundary condition when applying mask */ if( msb % 8 == 0 ) { p++; siglen -= 1; } - if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + + if( siglen < hlen + 2 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; mbedtls_md_init( &md_ctx ); if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } + goto exit; - mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; buf[0] &= 0xFF >> ( siglen * 8 - msb ); - while( p < buf + siglen && *p == 0 ) + while( p < hash_start - 1 && *p == 0 ) p++; - if( p == buf + siglen || - *p++ != 0x01 ) + if( *p++ != 0x01 ) { - mbedtls_md_free( &md_ctx ); - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; } - /* Actual salt len */ - slen -= p - buf; + observed_salt_len = hash_start - p; if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && - slen != (size_t) expected_salt_len ) + observed_salt_len != (size_t) expected_salt_len ) { - mbedtls_md_free( &md_ctx ); - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; } /* * Generate H = Hash( M' ) */ - mbedtls_md_starts( &md_ctx ); - mbedtls_md_update( &md_ctx, zeros, 8 ); - mbedtls_md_update( &md_ctx, hash, hashlen ); - mbedtls_md_update( &md_ctx, p, slen ); - mbedtls_md_finish( &md_ctx, result ); + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: mbedtls_md_free( &md_ctx ); - if( memcmp( p + slen, result, hlen ) == 0 ) - return( 0 ); - else - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + return( ret ); } /* @@ -1310,7 +2290,16 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, const unsigned char *hash, const unsigned char *sig ) { - mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + mbedtls_md_type_t mgf1_hash_id; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) ? (mbedtls_md_type_t) ctx->hash_id : md_alg; @@ -1335,109 +2324,74 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, const unsigned char *hash, const unsigned char *sig ) { - int ret; - size_t len, siglen, asn1_len; - unsigned char *p, *end; - mbedtls_md_type_t msg_md_alg; - const mbedtls_md_info_t *md_info; - mbedtls_asn1_buf oid; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + int ret = 0; + size_t sig_len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + sig_len = ctx->len; if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - siglen = ctx->len; + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ - if( siglen < 16 || siglen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, sig, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); - + ? mbedtls_rsa_public( ctx, sig, encoded ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); if( ret != 0 ) - return( ret ); - - p = buf; - - if( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - - while( *p != 0 ) - { - if( p >= buf + siglen - 1 || *p != 0xFF ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - p++; - } - p++; - - len = siglen - ( p - buf ); - - if( len == hashlen && md_alg == MBEDTLS_MD_NONE ) - { - if( memcmp( p, hash, hashlen ) == 0 ) - return( 0 ); - else - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - } - - md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - hashlen = mbedtls_md_get_size( md_info ); - - end = p + len; + goto cleanup; /* - * Parse the ASN.1 structure inside the PKCS#1 v1.5 structure + * Compare */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - if( asn1_len + 2 != len ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); +cleanup: - if( asn1_len + 6 + hashlen != len ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + if( encoded != NULL ) + { + mbedtls_platform_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } - if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + if( encoded_expected != NULL ) + { + mbedtls_platform_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } - oid.p = p; - p += oid.len; - - if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( md_alg != msg_md_alg ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - /* - * assume the algorithm parameters must be NULL - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( asn1_len != hashlen ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( memcmp( p, hash, hashlen ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - p += hashlen; - - if( p != end ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - return( 0 ); + return( ret ); } #endif /* MBEDTLS_PKCS1_V15 */ @@ -1453,6 +2407,14 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, const unsigned char *hash, const unsigned char *sig ) { + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + switch( ctx->padding ) { #if defined(MBEDTLS_PKCS1_V15) @@ -1478,6 +2440,8 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) { int ret; + RSA_VALIDATE_RET( dst != NULL ); + RSA_VALIDATE_RET( src != NULL ); dst->ver = src->ver; dst->len = src->len; @@ -1488,13 +2452,16 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); @@ -1514,17 +2481,33 @@ cleanup: */ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) { - mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN ); - mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); - mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D ); - mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); + mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); + mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); + mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free( &ctx->mutex ); #endif } +#endif /* !MBEDTLS_RSA_ALT */ + #if defined(MBEDTLS_SELF_TEST) #include "mbedtls/sha1.h" @@ -1564,21 +2547,6 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) "910E4168387E3C30AA1E00C339A79508" \ "8452DD96A9A5EA5D9DCA68DA636032AF" -#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ - "3C94D22288ACD763FD8E5600ED4A702D" \ - "F84198A5F06C2E72236AE490C93F07F8" \ - "3CC559CD27BC2D1CA488811730BB5725" - -#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ - "D8AAEA56749EA28623272E4F7D0592AF" \ - "7C1F1313CAC9471B5C523BFE592F517B" \ - "407A1BD76C164B93DA2D32A383E58357" - -#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ - "F38D18D2B2F0E2DD275AA977E2BF4411" \ - "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ - "A74206CEC169D74BF5A8C50D6F48EA08" - #define PT_LEN 24 #define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" @@ -1621,17 +2589,23 @@ int mbedtls_rsa_self_test( int verbose ) unsigned char sha1sum[20]; #endif + mbedtls_mpi K; + + mbedtls_mpi_init( &K ); mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); - rsa.len = KEY_LEN; - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); if( verbose != 0 ) mbedtls_printf( " RSA key validation: " ); @@ -1642,7 +2616,8 @@ int mbedtls_rsa_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "failed\n" ); - return( 1 ); + ret = 1; + goto cleanup; } if( verbose != 0 ) @@ -1650,26 +2625,29 @@ int mbedtls_rsa_self_test( int verbose ) memcpy( rsa_plaintext, RSA_PT, PT_LEN ); - if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN, - rsa_plaintext, rsa_ciphertext ) != 0 ) + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); - return( 1 ); + ret = 1; + goto cleanup; } if( verbose != 0 ) mbedtls_printf( "passed\n PKCS#1 decryption : " ); - if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len, - rsa_ciphertext, rsa_decrypted, - sizeof(rsa_decrypted) ) != 0 ) + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); - return( 1 ); + ret = 1; + goto cleanup; } if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) @@ -1677,7 +2655,8 @@ int mbedtls_rsa_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "failed\n" ); - return( 1 ); + ret = 1; + goto cleanup; } if( verbose != 0 ) @@ -1687,10 +2666,7 @@ int mbedtls_rsa_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " PKCS#1 data sign : " ); - mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ); - - if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, - sha1sum, rsa_ciphertext ) != 0 ) + if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); @@ -1698,16 +2674,29 @@ int mbedtls_rsa_self_test( int verbose ) return( 1 ); } - if( verbose != 0 ) - mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); - - if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, - sha1sum, rsa_ciphertext ) != 0 ) + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) { if( verbose != 0 ) mbedtls_printf( "failed\n" ); - return( 1 ); + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; } if( verbose != 0 ) @@ -1718,6 +2707,7 @@ int mbedtls_rsa_self_test( int verbose ) mbedtls_printf( "\n" ); cleanup: + mbedtls_mpi_free( &K ); mbedtls_rsa_free( &rsa ); #else /* MBEDTLS_PKCS1_V15 */ ((void) verbose); diff --git a/Externals/mbedtls/library/rsa_internal.c b/Externals/mbedtls/library/rsa_internal.c new file mode 100644 index 0000000000..9a42d47ceb --- /dev/null +++ b/Externals/mbedtls/library/rsa_internal.c @@ -0,0 +1,492 @@ +/* + * Helper functions for the RSA module + * + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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) + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa_internal.h" + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + /* + * When generating keys, the strongest security we support aims for an error + * rate of at most 2^-100 and we are aiming for the same certainty here as + * well. + */ + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ diff --git a/Externals/mbedtls/library/sha1.c b/Externals/mbedtls/library/sha1.c index 2ccf2a2f52..e8d4096fbb 100644 --- a/Externals/mbedtls/library/sha1.c +++ b/Externals/mbedtls/library/sha1.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_SHA1_C) #include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" #include @@ -45,12 +46,12 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ -#if !defined(MBEDTLS_SHA1_ALT) +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA1_ALT) /* * 32-bit integer manipulation macros (big endian) @@ -77,6 +78,8 @@ static void mbedtls_zeroize( void *v, size_t n ) { void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) { + SHA1_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); } @@ -85,20 +88,25 @@ void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); } void mbedtls_sha1_clone( mbedtls_sha1_context *dst, const mbedtls_sha1_context *src ) { + SHA1_VALIDATE( dst != NULL ); + SHA1_VALIDATE( src != NULL ); + *dst = *src; } /* * SHA-1 context setup */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) { + SHA1_VALIDATE_RET( ctx != NULL ); + ctx->total[0] = 0; ctx->total[1] = 0; @@ -107,13 +115,26 @@ void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + #if !defined(MBEDTLS_SHA1_PROCESS_ALT) -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) { uint32_t temp, W[16], A, B, C, D, E; + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); + GET_UINT32_BE( W[ 0], data, 0 ); GET_UINT32_BE( W[ 1], data, 4 ); GET_UINT32_BE( W[ 2], data, 8 ); @@ -264,19 +285,35 @@ void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[6 ctx->state[2] += C; ctx->state[3] += D; ctx->state[4] += E; + + return( 0 ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif #endif /* !MBEDTLS_SHA1_PROCESS_ALT */ /* * SHA-1 process buffer */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; uint32_t left; + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + if( ilen == 0 ) - return; + return( 0 ); left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -290,7 +327,10 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha1_process( ctx, ctx->buffer ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; ilen -= fill; left = 0; @@ -298,68 +338,138 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, while( ilen >= 64 ) { - mbedtls_sha1_process( ctx, input ); + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); } -static const unsigned char sha1_padding[64] = +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif /* * SHA-1 final digest */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) { - uint32_t last, padn; + int ret; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_sha1_update( ctx, sha1_padding, padn ); - mbedtls_sha1_update( ctx, msglen, 8 ); + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + /* + * Output final state + */ PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); PUT_UINT32_BE( ctx->state[3], output, 12 ); PUT_UINT32_BE( ctx->state[4], output, 16 ); + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + #endif /* !MBEDTLS_SHA1_ALT */ /* * output = SHA-1( input buffer ) */ -void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) { + int ret; mbedtls_sha1_context ctx; + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + mbedtls_sha1_init( &ctx ); - mbedtls_sha1_starts( &ctx ); - mbedtls_sha1_update( &ctx, input, ilen ); - mbedtls_sha1_finish( &ctx, output ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: mbedtls_sha1_free( &ctx ); + + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_sha1_ret( input, ilen, output ); +} +#endif + #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-1 test vectors @@ -371,7 +481,7 @@ static const unsigned char sha1_test_buf[3][57] = { "" } }; -static const int sha1_test_buflen[3] = +static const size_t sha1_test_buflen[3] = { 3, 56, 1000 }; @@ -406,28 +516,35 @@ int mbedtls_sha1_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); - mbedtls_sha1_starts( &ctx ); + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto fail; if( i == 2 ) { memset( buf, 'a', buflen = 1000 ); for( j = 0; j < 1000; j++ ) - mbedtls_sha1_update( &ctx, buf, buflen ); + { + ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } } else - mbedtls_sha1_update( &ctx, sha1_test_buf[i], - sha1_test_buflen[i] ); + { + ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } - mbedtls_sha1_finish( &ctx, sha1sum ); + if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) + goto fail; if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - ret = 1; - goto exit; + goto fail; } if( verbose != 0 ) @@ -437,6 +554,12 @@ int mbedtls_sha1_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "\n" ); + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + exit: mbedtls_sha1_free( &ctx ); diff --git a/Externals/mbedtls/library/sha256.c b/Externals/mbedtls/library/sha256.c index ad25d38333..8a540adfbe 100644 --- a/Externals/mbedtls/library/sha256.c +++ b/Externals/mbedtls/library/sha256.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_SHA256_C) #include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" #include @@ -48,12 +49,11 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ -#if !defined(MBEDTLS_SHA256_ALT) +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +#if !defined(MBEDTLS_SHA256_ALT) /* * 32-bit integer manipulation macros (big endian) @@ -80,6 +80,8 @@ do { \ void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) { + SHA256_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); } @@ -88,20 +90,26 @@ void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); } void mbedtls_sha256_clone( mbedtls_sha256_context *dst, const mbedtls_sha256_context *src ) { + SHA256_VALIDATE( dst != NULL ); + SHA256_VALIDATE( src != NULL ); + *dst = *src; } /* * SHA-256 context setup */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) { + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + ctx->total[0] = 0; ctx->total[1] = 0; @@ -131,8 +139,18 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) } ctx->is224 = is224; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + #if !defined(MBEDTLS_SHA256_PROCESS_ALT) static const uint32_t K[] = { @@ -179,12 +197,16 @@ static const uint32_t K[] = d += temp1; h = temp1 + temp2; \ } -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) { uint32_t temp1, temp2, W[64]; uint32_t A[8]; unsigned int i; + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); + for( i = 0; i < 8; i++ ) A[i] = ctx->state[i]; @@ -232,20 +254,35 @@ void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char da for( i = 0; i < 8; i++ ) ctx->state[i] += A[i]; + + return( 0 ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif #endif /* !MBEDTLS_SHA256_PROCESS_ALT */ /* * SHA-256 process buffer */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ) +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; uint32_t left; + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + if( ilen == 0 ) - return; + return( 0 ); left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -259,7 +296,10 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha256_process( ctx, ctx->buffer ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; ilen -= fill; left = 0; @@ -267,45 +307,80 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in while( ilen >= 64 ) { - mbedtls_sha256_process( ctx, input ); + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); } -static const unsigned char sha256_padding[64] = +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif /* * SHA-256 final digest */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) { - uint32_t last, padn; + int ret; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_sha256_update( ctx, sha256_padding, padn ); - mbedtls_sha256_update( ctx, msglen, 8 ); + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + /* + * Output final state + */ PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); @@ -316,25 +391,62 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32 if( ctx->is224 == 0 ) PUT_UINT32_BE( ctx->state[7], output, 28 ); + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + #endif /* !MBEDTLS_SHA256_ALT */ /* * output = SHA-256( input buffer ) */ -void mbedtls_sha256( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ) +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) { + int ret; mbedtls_sha256_context ctx; + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + mbedtls_sha256_init( &ctx ); - mbedtls_sha256_starts( &ctx, is224 ); - mbedtls_sha256_update( &ctx, input, ilen ); - mbedtls_sha256_finish( &ctx, output ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: mbedtls_sha256_free( &ctx ); + + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + mbedtls_sha256_ret( input, ilen, output, is224 ); +} +#endif + #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors @@ -346,7 +458,7 @@ static const unsigned char sha256_test_buf[3][57] = { "" } }; -static const int sha256_test_buflen[3] = +static const size_t sha256_test_buflen[3] = { 3, 56, 1000 }; @@ -415,28 +527,37 @@ int mbedtls_sha256_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); - mbedtls_sha256_starts( &ctx, k ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 ) + goto fail; if( j == 2 ) { memset( buf, 'a', buflen = 1000 ); for( j = 0; j < 1000; j++ ) - mbedtls_sha256_update( &ctx, buf, buflen ); + { + ret = mbedtls_sha256_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } else - mbedtls_sha256_update( &ctx, sha256_test_buf[j], - sha256_test_buflen[j] ); + { + ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 ) + goto fail; - mbedtls_sha256_finish( &ctx, sha256sum ); if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - ret = 1; - goto exit; + goto fail; } if( verbose != 0 ) @@ -446,6 +567,12 @@ int mbedtls_sha256_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "\n" ); + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + exit: mbedtls_sha256_free( &ctx ); mbedtls_free( buf ); diff --git a/Externals/mbedtls/library/sha512.c b/Externals/mbedtls/library/sha512.c index 724522ac68..941ecda762 100644 --- a/Externals/mbedtls/library/sha512.c +++ b/Externals/mbedtls/library/sha512.c @@ -33,6 +33,7 @@ #if defined(MBEDTLS_SHA512_C) #include "mbedtls/sha512.h" +#include "mbedtls/platform_util.h" #if defined(_MSC_VER) || defined(__WATCOMC__) #define UL64(x) x##ui64 @@ -54,12 +55,11 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ -#if !defined(MBEDTLS_SHA512_ALT) +#define SHA512_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) +#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +#if !defined(MBEDTLS_SHA512_ALT) /* * 64-bit integer manipulation macros (big endian) @@ -94,6 +94,8 @@ static void mbedtls_zeroize( void *v, size_t n ) { void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) { + SHA512_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); } @@ -102,20 +104,26 @@ void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); } void mbedtls_sha512_clone( mbedtls_sha512_context *dst, const mbedtls_sha512_context *src ) { + SHA512_VALIDATE( dst != NULL ); + SHA512_VALIDATE( src != NULL ); + *dst = *src; } /* * SHA-512 context setup */ -void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) { + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); + ctx->total[0] = 0; ctx->total[1] = 0; @@ -145,8 +153,18 @@ void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) } ctx->is384 = is384; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif + #if !defined(MBEDTLS_SHA512_PROCESS_ALT) /* @@ -196,12 +214,16 @@ static const uint64_t K[80] = UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) }; -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) { int i; uint64_t temp1, temp2, W[80]; uint64_t A, B, C, D, E, F, G, H; + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); + #define SHR(x,n) (x >> n) #define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) @@ -263,20 +285,35 @@ void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char da ctx->state[5] += F; ctx->state[6] += G; ctx->state[7] += H; + + return( 0 ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif #endif /* !MBEDTLS_SHA512_PROCESS_ALT */ /* * SHA-512 process buffer */ -void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, - size_t ilen ) +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; unsigned int left; + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + if( ilen == 0 ) - return; + return( 0 ); left = (unsigned int) (ctx->total[0] & 0x7F); fill = 128 - left; @@ -289,7 +326,10 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha512_process( ctx, ctx->buffer ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; ilen -= fill; left = 0; @@ -297,49 +337,80 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in while( ilen >= 128 ) { - mbedtls_sha512_process( ctx, input ); + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + input += 128; ilen -= 128; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); } -static const unsigned char sha512_padding[128] = +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif /* * SHA-512 final digest */ -void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ) +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) { - size_t last, padn; + int ret; + unsigned used; uint64_t high, low; - unsigned char msglen[16]; + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + + ctx->buffer[used++] = 0x80; + + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ high = ( ctx->total[0] >> 61 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); - PUT_UINT64_BE( high, msglen, 0 ); - PUT_UINT64_BE( low, msglen, 8 ); + PUT_UINT64_BE( high, ctx->buffer, 112 ); + PUT_UINT64_BE( low, ctx->buffer, 120 ); - last = (size_t)( ctx->total[0] & 0x7F ); - padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); - - mbedtls_sha512_update( ctx, sha512_padding, padn ); - mbedtls_sha512_update( ctx, msglen, 16 ); + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + /* + * Output final state + */ PUT_UINT64_BE( ctx->state[0], output, 0 ); PUT_UINT64_BE( ctx->state[1], output, 8 ); PUT_UINT64_BE( ctx->state[2], output, 16 ); @@ -352,25 +423,62 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64 PUT_UINT64_BE( ctx->state[6], output, 48 ); PUT_UINT64_BE( ctx->state[7], output, 56 ); } + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + #endif /* !MBEDTLS_SHA512_ALT */ /* * output = SHA-512( input buffer ) */ -void mbedtls_sha512( const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ) +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) { + int ret; mbedtls_sha512_context ctx; + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + mbedtls_sha512_init( &ctx ); - mbedtls_sha512_starts( &ctx, is384 ); - mbedtls_sha512_update( &ctx, input, ilen ); - mbedtls_sha512_finish( &ctx, output ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: mbedtls_sha512_free( &ctx ); + + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + mbedtls_sha512_ret( input, ilen, output, is384 ); +} +#endif + #if defined(MBEDTLS_SELF_TEST) /* @@ -384,7 +492,7 @@ static const unsigned char sha512_test_buf[3][113] = { "" } }; -static const int sha512_test_buflen[3] = +static const size_t sha512_test_buflen[3] = { 3, 112, 1000 }; @@ -471,28 +579,35 @@ int mbedtls_sha512_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); - mbedtls_sha512_starts( &ctx, k ); + if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 ) + goto fail; if( j == 2 ) { memset( buf, 'a', buflen = 1000 ); for( j = 0; j < 1000; j++ ) - mbedtls_sha512_update( &ctx, buf, buflen ); + { + ret = mbedtls_sha512_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } } else - mbedtls_sha512_update( &ctx, sha512_test_buf[j], - sha512_test_buflen[j] ); + { + ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } - mbedtls_sha512_finish( &ctx, sha512sum ); + if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 ) + goto fail; if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - ret = 1; - goto exit; + goto fail; } if( verbose != 0 ) @@ -502,6 +617,12 @@ int mbedtls_sha512_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "\n" ); + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + exit: mbedtls_sha512_free( &ctx ); mbedtls_free( buf ); diff --git a/Externals/mbedtls/library/ssl_cache.c b/Externals/mbedtls/library/ssl_cache.c index 9b62de2dcc..47867f132d 100644 --- a/Externals/mbedtls/library/ssl_cache.c +++ b/Externals/mbedtls/library/ssl_cache.c @@ -138,7 +138,7 @@ int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) { int ret = 1; #if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t = time( NULL ), oldest = 0; + mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; mbedtls_ssl_cache_entry *old = NULL; #endif mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; @@ -321,6 +321,7 @@ void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free( &cache->mutex ); #endif + cache->chain = NULL; } #endif /* MBEDTLS_SSL_CACHE_C */ diff --git a/Externals/mbedtls/library/ssl_ciphersuites.c b/Externals/mbedtls/library/ssl_ciphersuites.c index a762bf7c4f..518f7dde00 100644 --- a/Externals/mbedtls/library/ssl_ciphersuites.c +++ b/Externals/mbedtls/library/ssl_ciphersuites.c @@ -43,11 +43,11 @@ /* * Ordered from most preferred to least preferred in terms of security. * - * Current rule (except rc4, weak and null which come last): + * Current rule (except RC4 and 3DES, weak and null which come last): * 1. By key exchange: * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK * 2. By key length and cipher: - * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES + * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 * 4. By hash function used when relevant * 5. By key exchange/auth again: EC > non-EC @@ -57,6 +57,11 @@ static const int ciphersuite_preference[] = #if defined(MBEDTLS_SSL_CIPHERSUITES) MBEDTLS_SSL_CIPHERSUITES, #else + /* Chacha-Poly ephemeral suites */ + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + /* All AES-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, @@ -81,6 +86,14 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + /* All ARIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + /* All AES-128 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, @@ -105,12 +118,17 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, - /* All remaining >= 128-bit ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + /* All ARIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, /* The PSK ephemeral suites */ + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, @@ -121,6 +139,9 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, @@ -132,9 +153,9 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, - - MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, /* The ECJPAKE suite */ MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, @@ -161,6 +182,14 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + /* All ARIA-256 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + /* All AES-128 suites */ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_RSA_WITH_AES_128_CCM, @@ -183,27 +212,34 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - /* All remaining >= 128-bit suites */ - MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + /* All ARIA-128 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, - - MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, @@ -211,6 +247,8 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CCM, @@ -219,7 +257,19 @@ static const int ciphersuite_preference[] = MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + /* 3DES suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, /* RC4 suites */ @@ -266,6 +316,75 @@ static const int ciphersuite_preference[] = static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = { +#if defined(MBEDTLS_CHACHAPOLY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* MBEDTLS_CHACHAPOLY_C && + MBEDTLS_SHA256_C && + MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SHA1_C) @@ -1688,6 +1807,365 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = #endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ +#if defined(MBEDTLS_ARIA_C) + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA512_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#endif /* MBEDTLS_ARIA_C */ + + { 0, "", MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, 0, 0, 0, 0, 0 } @@ -1704,6 +2182,26 @@ const int *mbedtls_ssl_list_ciphersuites( void ) static int supported_ciphersuites[MAX_CIPHERSUITES]; static int supported_init = 0; +static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info ) +{ + (void)cs_info; + +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ + +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB || + cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC ) + { + return( 1 ); + } +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ + + return( 0 ); +} + const int *mbedtls_ssl_list_ciphersuites( void ) { /* @@ -1719,14 +2217,12 @@ const int *mbedtls_ssl_list_ciphersuites( void ) *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; p++ ) { -#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) const mbedtls_ssl_ciphersuite_t *cs_info; if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && - cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 ) -#else - if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL ) -#endif + !ciphersuite_is_removed( cs_info ) ) + { *(q++) = *p; + } } *q = 0; @@ -1817,9 +2313,28 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciph return( MBEDTLS_PK_NONE ); } } + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + #endif /* MBEDTLS_PK_C */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) { switch( info->key_exchange ) @@ -1829,13 +2344,14 @@ int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: return( 1 ); default: return( 0 ); } } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) diff --git a/Externals/mbedtls/library/ssl_cli.c b/Externals/mbedtls/library/ssl_cli.c index 223823b3cd..afced7a99c 100644 --- a/Externals/mbedtls/library/ssl_cli.c +++ b/Externals/mbedtls/library/ssl_cli.c @@ -48,10 +48,7 @@ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +#include "mbedtls/platform_util.h" #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -60,7 +57,7 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t hostname_len; *olen = 0; @@ -80,6 +77,13 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, } /* + * Sect. 3, RFC 6066 (TLS Extensions Definitions) + * + * In order to provide any of the server names, clients MAY include an + * extension of type "server_name" in the (extended) client hello. The + * "extension_data" field of this extension SHALL contain + * "ServerNameList" where: + * * struct { * NameType name_type; * select (name_type) { @@ -96,6 +100,7 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, * struct { * ServerName server_name_list<1..2^16-1> * } ServerNameList; + * */ *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); @@ -122,10 +127,13 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; + /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the + * initial ClientHello, in which case also adding the renegotiation + * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) return; @@ -163,7 +171,7 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t sig_alg_len = 0; const int *md; #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) @@ -248,7 +256,7 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; unsigned char *elliptic_curve_list = p + 6; size_t elliptic_curve_len = 0; const mbedtls_ecp_curve_info *info; @@ -264,11 +272,12 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECP_C) for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) - { - info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #else for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) +#endif { +#if defined(MBEDTLS_ECP_C) + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #endif if( info == NULL ) { @@ -289,11 +298,12 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECP_C) for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) - { - info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #else for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) +#endif { +#if defined(MBEDTLS_ECP_C) + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); #endif elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; @@ -319,7 +329,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -342,7 +352,7 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, *olen = 6; } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -352,7 +362,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, { int ret; unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; @@ -429,7 +439,7 @@ static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -462,7 +472,7 @@ static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -494,7 +504,7 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -528,7 +538,7 @@ static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -562,7 +572,7 @@ static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t tlen = ssl->session_negotiate->ticket_len; *olen = 0; @@ -606,7 +616,7 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t alpnlen = 0; const char **cur; @@ -704,6 +714,49 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) return( 0 ); } +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param suite_info cipher suite to validate + * \param ssl SSL context + * \param min_minor_ver Minimal minor version to accept a cipher suite + * \param max_minor_ver Maximal minor version to accept a cipher suite + * + * \return 0 if valid, else 1 + */ +static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl, + int min_minor_ver, int max_minor_ver ) +{ + (void) ssl; + if( suite_info == NULL ) + return( 1 ); + + if( suite_info->min_minor_ver > max_minor_ver || + suite_info->max_minor_ver < min_minor_ver ) + return( 1 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 1 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 1 ); +#endif + + return( 0 ); +} + static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { int ret; @@ -713,6 +766,10 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) unsigned char offer_compress; const int *ciphersuites; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + int uses_ec = 0; +#endif MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); @@ -856,39 +913,26 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); - if( ciphersuite_info == NULL ) + if( ssl_validate_ciphersuite( ciphersuite_info, ssl, + ssl->conf->min_minor_ver, + ssl->conf->max_minor_ver ) != 0 ) continue; - if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver || - ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver ) - continue; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) - continue; -#endif - -#if defined(MBEDTLS_ARC4_C) - if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) - continue; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && - mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - continue; -#endif - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", ciphersuites[i] ) ); +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); +#endif + n++; *p++ = (unsigned char)( ciphersuites[i] >> 8 ); *p++ = (unsigned char)( ciphersuites[i] ); } + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) ); + /* * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ @@ -896,6 +940,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) #endif { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); n++; @@ -915,8 +960,6 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) *q++ = (unsigned char)( n >> 7 ); *q++ = (unsigned char)( n << 1 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); - #if defined(MBEDTLS_ZLIB_SUPPORT) offer_compress = 1; #else @@ -924,7 +967,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) #endif /* - * We don't support compression with DTLS right now: is many records come + * We don't support compression with DTLS right now: if many records come * in the same datagram, uncompressing one could overwrite the next one. * We don't want to add complexity for handling that case unless there is * an actual need for it. @@ -961,6 +1004,8 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ext_len += olen; #endif + /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added + * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; @@ -974,11 +1019,14 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; + if( uses_ec ) + { + ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -1040,12 +1088,21 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) mbedtls_ssl_send_flight_completed( ssl ); #endif - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); return( 0 ); @@ -1055,8 +1112,6 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - int ret; - #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) { @@ -1069,10 +1124,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } } @@ -1082,10 +1135,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, if( len != 1 || buf[0] != 0x00 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1108,6 +1159,9 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, len != 1 || buf[0] != ssl->conf->mfl_code ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1123,6 +1177,9 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || len != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1143,6 +1200,9 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || len != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1163,6 +1223,9 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || len != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1182,6 +1245,9 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || len != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1202,12 +1268,14 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, size_t list_size; const unsigned char *p; - list_size = buf[0]; - if( list_size + 1 != len ) + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } + list_size = buf[0]; p = buf + 1; while( list_size > 0 ) @@ -1217,7 +1285,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, { #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) ssl->handshake->ecdh_ctx.point_format = p[0]; -#endif +#endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ssl->handshake->ecjpake_ctx.point_format = p[0]; #endif @@ -1230,9 +1298,11 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, } MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -1258,6 +1328,8 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, buf, len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( ret ); } @@ -1274,7 +1346,12 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, /* If we didn't send it, the server shouldn't send it */ if( ssl->conf->alpn_list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } /* * opaque ProtocolName<1..2^8-1>; @@ -1288,15 +1365,27 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } list_len = ( buf[0] << 8 ) | buf[1]; if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } name_len = buf[2]; if( name_len != list_len - 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } /* Check that the server chosen protocol was in our list and save it */ for( p = ssl->conf->alpn_list; *p != NULL; p++ ) @@ -1309,6 +1398,9 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, } } + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } #endif /* MBEDTLS_SSL_ALPN */ @@ -1403,16 +1495,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #endif int handshake_failure = 0; const mbedtls_ssl_ciphersuite_t *suite_info; -#if defined(MBEDTLS_DEBUG_C) - uint32_t t; -#endif MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); buf = ssl->in_msg; - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { + /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); } @@ -1433,11 +1523,15 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); + + ssl->keep_current_message = 1; return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -1464,6 +1558,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1501,13 +1597,11 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); } -#if defined(MBEDTLS_DEBUG_C) - t = ( (uint32_t) buf[2] << 24 ) - | ( (uint32_t) buf[3] << 16 ) - | ( (uint32_t) buf[4] << 8 ) - | ( (uint32_t) buf[5] ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); -#endif + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", + ( (uint32_t) buf[2] << 24 ) | + ( (uint32_t) buf[3] << 16 ) | + ( (uint32_t) buf[4] << 8 ) | + ( (uint32_t) buf[5] ) ) ); memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); @@ -1518,6 +1612,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( n > 32 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1530,6 +1626,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } } @@ -1540,6 +1638,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) else { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1567,6 +1667,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #endif/* MBEDTLS_ZLIB_SUPPORT */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); } @@ -1578,6 +1680,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ssl->transform_negotiate->ciphersuite_info == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -1615,6 +1719,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( ret ); } } @@ -1625,26 +1731,17 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); - suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); - if( suite_info == NULL -#if defined(MBEDTLS_ARC4_C) - || ( ssl->conf->arc4_disabled && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); - + /* + * Perform cipher suite validation in same way as in ssl_write_client_hello. + */ i = 0; while( 1 ) { if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1655,6 +1752,25 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } } + suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, ssl->minor_ver ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ecrs_enabled = 1; + } +#endif + if( comp != MBEDTLS_SSL_COMPRESS_NULL #if defined(MBEDTLS_ZLIB_SUPPORT) && comp != MBEDTLS_SSL_COMPRESS_DEFLATE @@ -1662,6 +1778,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } ssl->session_negotiate->compression = comp; @@ -1680,6 +1798,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ext_size + 4 > ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1850,9 +1970,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( handshake_failure == 1 ) { - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1908,8 +2027,14 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char * static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) { const mbedtls_ecp_curve_info *curve_info; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif - curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); + curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); if( curve_info == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); @@ -1919,14 +2044,15 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); #if defined(MBEDTLS_ECP_C) - if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 ) + if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) #else if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || ssl->handshake->ecdh_ctx.grp.nbits > 521 ) #endif return( -1 ); - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); return( 0 ); } @@ -1957,6 +2083,10 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, (const unsigned char **) p, end ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } @@ -1986,12 +2116,19 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, * * opaque psk_identity_hint<0..2^16-1>; */ + if( end - (*p) < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " + "(psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } len = (*p)[0] << 8 | (*p)[1]; *p += 2; - if( (*p) + len > end ) + if( end - (*p) < (int) len ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (psk_identity_hint length)" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " + "(psk_identity_hint length)" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -2020,7 +2157,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; unsigned char *p = ssl->handshake->premaster + pms_offset; - if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); @@ -2063,7 +2200,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, p, ssl->handshake->pmslen, ssl->out_msg + offset + len_bytes, olen, - MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes, + MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); @@ -2133,8 +2270,8 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, */ if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm " - "that was not offered" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm %d that was not offered", + *(p)[0] ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -2192,8 +2329,9 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) { int ret; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - unsigned char *p, *end; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + unsigned char *p = NULL, *end = NULL; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); @@ -2216,6 +2354,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( ret ); } @@ -2228,7 +2368,15 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) + { + goto start_processing; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -2237,6 +2385,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2249,14 +2399,26 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) { - ssl->record_read = 1; + /* Current message is probably either + * CertificateRequest or ServerHelloDone */ + ssl->keep_current_message = 1; goto exit; } - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key exchange message must " + "not be skipped" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; + +start_processing: +#endif p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); end = ssl->in_msg + ssl->in_hslen; MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); @@ -2270,6 +2432,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } /* FALLTROUGH */ @@ -2291,6 +2455,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2307,6 +2473,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2322,6 +2490,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2332,12 +2502,8 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) { size_t sig_len, hashlen; unsigned char hash[64]; @@ -2345,6 +2511,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); size_t params_len = p - params; + void *rs_ctx = NULL; /* * Handle the digitally-signed structure @@ -2356,12 +2523,16 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) &md_alg, &pk_alg ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2387,12 +2558,22 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) /* * Read signature */ + + if( p > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } sig_len = ( p[0] << 8 ) | p[1]; p += 2; - if( end != p + sig_len ) + if( p != end - sig_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -2405,39 +2586,11 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) defined(MBEDTLS_SSL_PROTO_TLS1_1) if( md_alg == MBEDTLS_MD_NONE ) { - mbedtls_md5_context mbedtls_md5; - mbedtls_sha1_context mbedtls_sha1; - - mbedtls_md5_init( &mbedtls_md5 ); - mbedtls_sha1_init( &mbedtls_sha1 ); - hashlen = 36; - - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); - */ - mbedtls_md5_starts( &mbedtls_md5 ); - mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); - mbedtls_md5_update( &mbedtls_md5, params, params_len ); - mbedtls_md5_finish( &mbedtls_md5, hash ); - - mbedtls_sha1_starts( &mbedtls_sha1 ); - mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); - mbedtls_sha1_update( &mbedtls_sha1, params, params_len ); - mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); - - mbedtls_md5_free( &mbedtls_md5 ); - mbedtls_sha1_free( &mbedtls_sha1 ); + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params, + params_len ); + if( ret != 0 ) + return( ret ); } else #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ @@ -2446,32 +2599,11 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) defined(MBEDTLS_SSL_PROTO_TLS1_2) if( md_alg != MBEDTLS_MD_NONE ) { - mbedtls_md_context_t ctx; - - mbedtls_md_init( &ctx ); - - /* Info from md_alg will be used instead */ - hashlen = 0; - - /* - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * }; - */ - if( ( ret = mbedtls_md_setup( &ctx, - mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + params, params_len, + md_alg ); + if( ret != 0 ) return( ret ); - } - - mbedtls_md_starts( &ctx ); - mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); - mbedtls_md_update( &ctx, params, params_len ); - mbedtls_md_finish( &ctx, hash ); - mbedtls_md_free( &ctx ); } else #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ @@ -2481,12 +2613,13 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); if( ssl->session_negotiate->peer_cert == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2496,19 +2629,34 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); } - if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, - md_alg, hash, hashlen, p, sig_len ) ) != 0 ) +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_verify_restartable( + &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) { +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } } -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ exit: ssl->state++; @@ -2518,23 +2666,15 @@ exit: return( 0 ); } -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if ! defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) { - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); ssl->state++; @@ -2544,58 +2684,51 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } -#else +#else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) { int ret; unsigned char *buf; size_t n = 0; size_t cert_type_len = 0, dn_len = 0; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); ssl->state++; return( 0 ); } - if( ssl->record_read == 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - ssl->record_read = 1; + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); } - ssl->client_auth = 0; - ssl->state++; + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } - if( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ) - ssl->client_auth++; + ssl->state++; + ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", ssl->client_auth ? "a" : "no" ) ); if( ssl->client_auth == 0 ) + { + /* Current message is probably the ServerHelloDone */ + ssl->keep_current_message = 1; goto exit; - - ssl->record_read = 0; + } /* * struct { @@ -2624,12 +2757,31 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) buf = ssl->in_msg; /* certificate_types */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; n = cert_type_len; - if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + /* + * In the subsequent code there are two paths that read from buf: + * * the length of the signature algorithms field (if minor version of + * SSL is 3), + * * distinguished name length otherwise. + * Both reach at most the index: + * ...hdr_len + 2 + n, + * therefore the buffer length at this point must be greater than that + * regardless of the actual code path. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } @@ -2640,22 +2792,40 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); #if defined(MBEDTLS_DEBUG_C) - unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + unsigned char* sig_alg; size_t i; +#endif + /* + * The furthest access in buf is in the loop few lines below: + * sig_alg[i + 1], + * where: + * sig_alg = buf + ...hdr_len + 3 + n, + * max(i) = sig_alg_len - 1. + * Therefore the furthest access is: + * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], + * which reduces to: + * buf[...hdr_len + 3 + n + sig_alg_len], + * which is one less than we need the buf to be. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n + sig_alg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +#if defined(MBEDTLS_DEBUG_C) + sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; for( i = 0; i < sig_alg_len; i += 2 ) { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d,%d", sig_alg[i], sig_alg[i + 1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d" + ",%d", sig_alg[i], sig_alg[i + 1] ) ); } #endif n += 2 + sig_alg_len; - - if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); - } } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ @@ -2667,6 +2837,8 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } @@ -2675,12 +2847,7 @@ exit: return( 0 ); } -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) { @@ -2688,26 +2855,24 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); - if( ssl->record_read == 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } - ssl->record_read = 0; if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); } @@ -2727,7 +2892,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) { int ret; size_t i, n; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); @@ -2784,6 +2950,16 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) */ i = 4; +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + { + if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) + goto ecdh_calc_secret; + + mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + } +#endif + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, &ssl->out_msg[i], 1000, @@ -2791,11 +2967,27 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + { + ssl->handshake->ecrs_n = n; + ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; + } + +ecdh_calc_secret: + if( ssl->handshake->ecrs_enabled ) + n = ssl->handshake->ecrs_n; +#endif if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, ssl->handshake->premaster, @@ -2803,10 +2995,15 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || @@ -2814,10 +3011,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) { /* * opaque psk_identity<0..2^16-1>; @@ -2831,7 +3025,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 4; n = ssl->conf->psk_identity_len; - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " "SSL buffer too short" ) ); @@ -2867,7 +3061,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) */ n = ssl->handshake->dhm_ctx.len; - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" " or SSL buffer too short" ) ); @@ -2896,7 +3090,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) * ClientECDiffieHellmanPublic public; */ ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, - &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i, + &ssl->out_msg[i], MBEDTLS_SSL_OUT_CONTENT_LEN - i, ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { @@ -2904,7 +3098,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) return( ret ); } - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ @@ -2937,7 +3132,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 4; ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n, + ssl->out_msg + i, MBEDTLS_SSL_OUT_CONTENT_LEN - i, &n, ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { @@ -2968,9 +3163,9 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -2987,7 +3182,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) { - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; int ret; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); @@ -3016,15 +3212,25 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; size_t n = 0, offset = 0; unsigned char hash[48]; unsigned char *hash_start = hash; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; unsigned int hashlen; + void *rs_ctx = NULL; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) + { + goto sign; + } +#endif + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); @@ -3056,8 +3262,15 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) } /* - * Make an RSA signature of the handshake digests + * Make a signature of the handshake digests */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; + +sign: +#endif + ssl->handshake->calc_verify( ssl, hash ); #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ @@ -3134,11 +3347,21 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), + md_alg, hash_start, hashlen, ssl->out_msg + 6 + offset, &n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } @@ -3151,9 +3374,9 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -3179,7 +3402,7 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -3188,6 +3411,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -3205,19 +3430,23 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); } msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) | - ( msg[2] << 8 ) | ( msg[3] ); + lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); ticket_len = ( msg[4] << 8 ) | ( msg[5] ); if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); } @@ -3234,8 +3463,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) if( ticket_len == 0 ) return( 0 ); - mbedtls_zeroize( ssl->session_negotiate->ticket, - ssl->session_negotiate->ticket_len ); + mbedtls_platform_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); mbedtls_free( ssl->session_negotiate->ticket ); ssl->session_negotiate->ticket = NULL; ssl->session_negotiate->ticket_len = 0; @@ -3243,6 +3472,8 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } @@ -3285,10 +3516,10 @@ int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) return( ret ); } -#endif +#endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Change state now, so that it is right in mbedtls_ssl_read_record(), used * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ diff --git a/Externals/mbedtls/library/ssl_cookie.c b/Externals/mbedtls/library/ssl_cookie.c index 9fb32de7a6..56e9bdd2bf 100644 --- a/Externals/mbedtls/library/ssl_cookie.c +++ b/Externals/mbedtls/library/ssl_cookie.c @@ -40,14 +40,10 @@ #include "mbedtls/ssl_cookie.h" #include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" #include -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is * available. Try SHA-256 first, 512 wastes resources since we need to stay @@ -98,10 +94,10 @@ void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) mbedtls_md_free( &ctx->hmac_ctx ); #if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); + mbedtls_mutex_free( &ctx->mutex ); #endif - mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); } int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, @@ -122,7 +118,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, if( ret != 0 ) return( ret ); - mbedtls_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); return( 0 ); } diff --git a/Externals/mbedtls/library/ssl_srv.c b/Externals/mbedtls/library/ssl_srv.c index fc0d2d7b42..bc77f80203 100644 --- a/Externals/mbedtls/library/ssl_srv.c +++ b/Externals/mbedtls/library/ssl_srv.c @@ -38,6 +38,7 @@ #include "mbedtls/debug.h" #include "mbedtls/ssl.h" #include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" #include @@ -49,13 +50,6 @@ #include "mbedtls/platform_time.h" #endif -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} -#endif - #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, const unsigned char *info, @@ -97,20 +91,31 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + if( len < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( servername_list_size + 2 != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } p = buf + 2; - while( servername_list_size > 0 ) + while( servername_list_size > 2 ) { hostname_len = ( ( p[1] << 8 ) | p[2] ); if( hostname_len + 3 > servername_list_size ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -135,6 +140,8 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, if( servername_list_size != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -146,8 +153,6 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - int ret; - #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) { @@ -158,10 +163,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ssl->verify_data_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } } @@ -171,10 +174,8 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, if( len != 1 || buf[0] != 0x0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -186,47 +187,90 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* + * Status of the implementation of signature-algorithms extension: + * + * Currently, we are only considering the signature-algorithm extension + * to pick a ciphersuite which allows us to send the ServerKeyExchange + * message with a signature-hash combination that the user allows. + * + * We do *not* check whether all certificates in our certificate + * chain are signed with an allowed signature-hash pair. + * This needs to be done at a later stage. + * + */ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { size_t sig_alg_list_size; + const unsigned char *p; const unsigned char *end = buf + len; - const int *md_cur; + mbedtls_md_type_t md_cur; + mbedtls_pk_type_t sig_cur; + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( sig_alg_list_size + 2 != len || sig_alg_list_size % 2 != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } - /* - * For now, ignore the SignatureAlgorithm part and rely on offered - * ciphersuites only for that part. To be fixed later. + /* Currently we only guarantee signing the ServerKeyExchange message according + * to the constraints specified in this extension (see above), so it suffices + * to remember only one suitable hash for each possible signature algorithm. * - * So, just look at the HashAlgorithm part. + * This will change when we also consider certificate signatures, + * in which case we will need to remember the whole signature-hash + * pair list from the extension. */ - for( md_cur = ssl->conf->sig_hashes; *md_cur != MBEDTLS_MD_NONE; md_cur++ ) { - for( p = buf + 2; p < end; p += 2 ) { - if( *md_cur == (int) mbedtls_ssl_md_alg_from_hash( p[0] ) ) { - ssl->handshake->sig_alg = p[0]; - goto have_sig_alg; - } + + for( p = buf + 2; p < end; p += 2 ) + { + /* Silently ignore unknown signature or hash algorithms. */ + + if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" + " unknown sig alg encoding %d", p[1] ) ); + continue; + } + + /* Check if we support the hash the user proposes */ + md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); + if( md_cur == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " unknown hash alg encoding %d", p[0] ) ); + continue; + } + + if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) + { + mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " match sig %d and hash %d", + sig_cur, md_cur ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " + "hash alg %d not supported", md_cur ) ); } } - /* Some key echanges do not need signatures at all */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no signature_algorithm in common" ) ); - return( 0 ); - -have_sig_alg: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", - ssl->handshake->sig_alg ) ); - return( 0 ); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && @@ -242,11 +286,19 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, const unsigned char *p; const mbedtls_ecp_curve_info *curve_info, **curves; + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); if( list_size + 2 != len || list_size % 2 != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -254,6 +306,8 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, if( ssl->handshake->curves != NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -264,7 +318,11 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, our_size = MBEDTLS_ECP_DP_MAX; if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } ssl->handshake->curves = curves; @@ -293,12 +351,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, size_t list_size; const unsigned char *p; - list_size = buf[0]; - if( list_size + 1 != len ) + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } + list_size = buf[0]; p = buf + 1; while( list_size > 0 ) @@ -342,6 +402,8 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, buf, len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( ret ); } @@ -360,6 +422,8 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -377,6 +441,8 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, if( len != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -397,6 +463,8 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, if( len != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -420,6 +488,8 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, if( len != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -496,7 +566,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); /* Zeroize instead of free as we copied the content */ - mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); @@ -531,32 +601,56 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } list_len = ( buf[0] << 8 ) | buf[1]; if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Validate peer's list (lengths) + */ + start = buf + 2; + end = buf + len; + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + /* Current identifier must fit in list */ + if( cur_len > (size_t)( end - theirs ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } /* * Use our order of preference */ - start = buf + 2; - end = buf + len; for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) { ours_len = strlen( *ours ); for( theirs = start; theirs != end; theirs += cur_len ) { - /* If the list is well formed, we should get equality first */ - if( theirs > end ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - cur_len = *theirs++; - /* Empty strings MUST NOT be included */ - if( cur_len == 0 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - if( cur_len == ours_len && memcmp( theirs, *ours, cur_len ) == 0 ) { @@ -607,7 +701,8 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) { mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; - mbedtls_pk_type_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + mbedtls_pk_type_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); uint32_t flags; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -633,7 +728,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", cur->cert ); - if( ! mbedtls_pk_can_do( cur->key, pk_alg ) ) + if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); continue; @@ -657,7 +752,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_ECDSA_C) if( pk_alg == MBEDTLS_PK_ECDSA && - ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) + ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); continue; @@ -710,6 +805,11 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, { const mbedtls_ssl_ciphersuite_t *suite_info; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_pk_type_t sig_type; +#endif + suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); if( suite_info == NULL ) { @@ -776,6 +876,25 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, } #endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); + if( sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %d", sig_type ) ); + return( 0 ); + } + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + #if defined(MBEDTLS_X509_CRT_PARSE_C) /* * Final check: if ciphersuite requires us to have a @@ -813,10 +932,8 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -962,9 +1079,8 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " "during renegotiation" ) ); - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -1002,11 +1118,9 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) ciphersuite_info = NULL; #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) - { for( i = 0; ciphersuites[i] != 0; i++ ) #else for( i = 0; ciphersuites[i] != 0; i++ ) - { for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) #endif { @@ -1024,7 +1138,6 @@ static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) if( ciphersuite_info != NULL ) goto have_ciphersuite_v2; } - } if( got_common_suite ) { @@ -1051,10 +1164,8 @@ have_ciphersuite_v2: ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1067,6 +1178,9 @@ have_ciphersuite_v2: } #endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +/* This function doesn't alert on errors that happen early during + ClientHello parsing because they might indicate that the client is + not talking SSL/TLS at all and would not understand our alert. */ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) { int ret, got_common_suite; @@ -1085,6 +1199,15 @@ static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) const mbedtls_ssl_ciphersuite_t *ciphersuite_info; int major, minor; + /* If there is no signature-algorithm extension present, + * we need to fall back to the default values for allowed + * signature-hash pairs. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + int sig_hash_alg_ext_present = 0; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) @@ -1101,6 +1224,7 @@ read_record_header: { if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) { + /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); return( ret ); } @@ -1113,7 +1237,7 @@ read_record_header: if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) #endif if( ( buf[0] & 0x80 ) != 0 ) - return ssl_parse_client_hello_v2( ssl ); + return( ssl_parse_client_hello_v2( ssl ) ); #endif MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); @@ -1170,7 +1294,7 @@ read_record_header: return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } - memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 ); + memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 ); #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) @@ -1198,13 +1322,14 @@ read_record_header: else #endif { - if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } - if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); return( ret ); @@ -1352,10 +1477,8 @@ read_record_header: " [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver, ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); } @@ -1383,6 +1506,8 @@ read_record_header: sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1406,6 +1531,8 @@ read_record_header: if( cookie_offset + 1 + cookie_len + 2 > msg_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1438,6 +1565,7 @@ read_record_header: /* We know we didn't send a cookie, so it should be empty */ if( cookie_len != 0 ) { + /* This may be an attacker's probe, so don't send an alert */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1462,6 +1590,8 @@ read_record_header: ( ciph_len % 2 ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1480,6 +1610,8 @@ read_record_header: comp_len + comp_offset + 1 > msg_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1518,6 +1650,8 @@ read_record_header: if( msg_len < ext_offset + 2 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1528,6 +1662,8 @@ read_record_header: msg_len != ext_offset + 2 + ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } } @@ -1539,14 +1675,22 @@ read_record_header: while( ext_len != 0 ) { - unsigned int ext_id = ( ( ext[0] << 8 ) - | ( ext[1] ) ); - unsigned int ext_size = ( ( ext[2] << 8 ) - | ( ext[3] ) ); + unsigned int ext_id; + unsigned int ext_size; + if ( ext_len < 4 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); + ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) ); if( ext_size + 4 > ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } switch( ext_id ) @@ -1577,15 +1721,13 @@ read_record_header: #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) case MBEDTLS_TLS_EXT_SIG_ALG: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - break; -#endif + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); if( ret != 0 ) return( ret ); + + sig_hash_alg_ext_present = 1; break; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ @@ -1692,6 +1834,8 @@ read_record_header: if( ext_len > 0 && ext_len < 4 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } } @@ -1700,7 +1844,7 @@ read_record_header: #endif #if defined(MBEDTLS_SSL_FALLBACK_SCSV) - for( i = 0, p = buf + 41 + sess_len; i < ciph_len; i += 2, p += 2 ) + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) { if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) @@ -1722,6 +1866,26 @@ read_record_header: } #endif /* MBEDTLS_SSL_FALLBACK_SCSV */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + + /* + * Try to fall back to default hash SHA1 if the client + * hasn't provided any preferred signature-hash combinations. + */ + if( sig_hash_alg_ext_present == 0 ) + { + mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; + + if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) + md_default = MBEDTLS_MD_NONE; + + mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + /* * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ @@ -1733,11 +1897,10 @@ read_record_header: #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) ); - - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } #endif @@ -1781,9 +1944,8 @@ read_record_header: if( handshake_failure == 1 ) { - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); } @@ -1797,11 +1959,9 @@ read_record_header: ciphersuite_info = NULL; #if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) - { for( i = 0; ciphersuites[i] != 0; i++ ) #else for( i = 0; ciphersuites[i] != 0; i++ ) - { for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) #endif { @@ -1818,19 +1978,20 @@ read_record_header: if( ciphersuite_info != NULL ) goto have_ciphersuite; } - } if( got_common_suite ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " "but none of them usable" ) ); - mbedtls_ssl_send_fatal_handshake_failure( ssl ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); } else { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - mbedtls_ssl_send_fatal_handshake_failure( ssl ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); } @@ -1847,6 +2008,28 @@ have_ciphersuite: mbedtls_ssl_recv_flight_completed( ssl ); #endif + /* Debugging-only output for testsuite */ +#if defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); + if( sig_alg != MBEDTLS_PK_NONE ) + { + mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " + "%d - should not happen", sig_alg ) ); + } + } +#endif + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); return( 0 ); @@ -1886,7 +2069,7 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *suite = NULL; const mbedtls_cipher_info_t *cipher = NULL; - if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { *olen = 0; @@ -2077,7 +2260,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, { int ret; unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; @@ -2184,7 +2367,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) cookie_len_byte = p++; if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, - &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN, + &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, ssl->cli_id, ssl->cli_id_len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); @@ -2201,12 +2384,21 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); return( 0 ); @@ -2406,8 +2598,12 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; + if ( mbedtls_ssl_ciphersuite_uses_ec( + mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) ) + { + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) @@ -2437,7 +2633,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; - ret = mbedtls_ssl_write_record( ssl ); + ret = mbedtls_ssl_write_handshake_msg( ssl ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); @@ -2452,7 +2648,8 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) { - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); @@ -2474,11 +2671,12 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; size_t dn_size, total_dn_size; /* excluding length bytes */ size_t ct_len, sa_len; /* including length bytes */ unsigned char *buf, *p; - const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; const mbedtls_x509_crt *crt; int authmode; @@ -2588,35 +2786,40 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) * opaque DistinguishedName<1..2^16-1>; */ p += 2; -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_ca_chain != NULL ) - crt = ssl->handshake->sni_ca_chain; - else -#endif - crt = ssl->conf->ca_chain; total_dn_size = 0; - while( crt != NULL && crt->version != 0 ) + + if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) { - dn_size = crt->subject_raw.len; +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; - if( end < p || - (size_t)( end - p ) < dn_size || - (size_t)( end - p ) < 2 + dn_size ) + while( crt != NULL && crt->version != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); - break; + dn_size = crt->subject_raw.len; + + if( end < p || + (size_t)( end - p ) < dn_size || + (size_t)( end - p ) < 2 + dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; } - - *p++ = (unsigned char)( dn_size >> 8 ); - *p++ = (unsigned char)( dn_size ); - memcpy( p, crt->subject_raw.p, dn_size ); - p += dn_size; - - MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); - - total_dn_size += 2 + dn_size; - crt = crt->next; } ssl->out_msglen = p - buf; @@ -2625,7 +2828,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); - ret = mbedtls_ssl_write_record( ssl ); + ret = mbedtls_ssl_write_handshake_msg( ssl ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); @@ -2663,94 +2866,108 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; + size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN + - sig_start ); + int ret = ssl->conf->f_async_resume( ssl, + sig_start, signature_len, sig_max_len ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); + return( ret ); +} +#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + +/* Prepare the ServerKeyExchange message, up to and including + * calculating the signature if any, but excluding formatting the + * signature and sending the message. */ +static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) { - int ret; - size_t n = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + unsigned char *dig_signed = NULL; +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - unsigned char *p = ssl->out_msg + 4; - unsigned char *dig_signed = p; - size_t dig_signed_len = 0, len; - ((void) dig_signed); - ((void) dig_signed_len); - ((void) len); -#endif + (void) ciphersuite_info; /* unused in some configurations */ +#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + (void) signature_len; +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); - ssl->state++; - return( 0 ); - } -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) - { - ssl_get_ecdh_params_from_cert( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); - ssl->state++; - return( 0 ); - } -#endif + /* + * + * Part 1: Provide key exchange parameters for chosen ciphersuite. + * + */ + /* + * - ECJPAKE key exchanges + */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) { - size_t jlen; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; + int ret; + size_t len = 0; - ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p, &jlen, ssl->conf->f_rng, ssl->conf->p_rng ); + ret = mbedtls_ecjpake_write_round_two( + &ssl->handshake->ecjpake_ctx, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); return( ret ); } - p += jlen; - n += jlen; + ssl->out_msglen += len; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + /* + * For (EC)DHE key exchanges with PSK, parameters are prefixed by support + * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, + * we use empty support identity hints here. + **/ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) { - /* Note: we don't support identity hints, until someone asks - * for them. */ - *(p++) = 0x00; - *(p++) = 0x00; - - n += 2; + ssl->out_msg[ssl->out_msglen++] = 0x00; + ssl->out_msg[ssl->out_msglen++] = 0x00; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + /* + * - DHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) { + int ret; + size_t len = 0; + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); @@ -2766,39 +2983,42 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ - if( ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->conf->dhm_P ) ) != 0 || - ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->conf->dhm_G ) ) != 0 ) + if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx, + &ssl->conf->dhm_P, + &ssl->conf->dhm_G ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_mpi_copy", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret ); return( ret ); } - if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + if( ( ret = mbedtls_dhm_make_params( + &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + ssl->out_msg + ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); return( ret ); } - dig_signed = p; - dig_signed_len = len; +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif - p += len; - n += len; + ssl->out_msglen += len; MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); } -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED */ + /* + * - ECDHE key exchanges + */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) { /* * Ephemeral ECDH parameters: @@ -2810,6 +3030,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) */ const mbedtls_ecp_curve_info **curve = NULL; const mbedtls_ecp_group_id *gid; + int ret; + size_t len = 0; /* Match our preference list against the offered curves */ for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) @@ -2826,54 +3048,73 @@ curve_matching_done: MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); - if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, - (*curve)->grp_id ) ) != 0 ) + if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx, + (*curve)->grp_id ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); return( ret ); } - if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, - p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + if( ( ret = mbedtls_ecdh_make_params( + &ssl->handshake->ecdh_ctx, &len, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); return( ret ); } - dig_signed = p; - dig_signed_len = len; +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif - p += len; - n += len; + ssl->out_msglen += len; - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); } #endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + /* + * + * Part 2: For key exchanges involving the server signing the + * exchange parameters, compute and add the signature here. + * + */ +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) { - size_t signature_len = 0; - unsigned int hashlen = 0; - unsigned char hash[64]; - mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + size_t hashlen = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + int ret; /* - * Choose hash algorithm. NONE means MD5 + SHA1 here. + * 2.1: Choose hash algorithm: + * A: For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. + * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 + * (RFC 4492, Sec. 5.4) + * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) */ + + mbedtls_md_type_t md_alg; + #if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t sig_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { - md_alg = mbedtls_ssl_md_alg_from_hash( ssl->handshake->sig_alg ); - - if( md_alg == MBEDTLS_MD_NONE ) + /* A: For TLS 1.2, obey signature-hash-algorithm extension + * (RFC 5246, Sec. 7.4.1.4.1). */ + if( sig_alg == MBEDTLS_PK_NONE || + ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ) ) == MBEDTLS_MD_NONE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + /* (... because we choose a cipher suite + * only if there is a matching hash.) */ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } } @@ -2881,57 +3122,34 @@ curve_matching_done: #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ciphersuite_info->key_exchange == - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) { + /* B: Default hash SHA1 */ md_alg = MBEDTLS_MD_SHA1; } else -#endif +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ { + /* C: MD5 + SHA1 */ md_alg = MBEDTLS_MD_NONE; } + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); + /* - * Compute the hash to be signed + * 2.2: Compute the hash to be signed */ #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) if( md_alg == MBEDTLS_MD_NONE ) { - mbedtls_md5_context mbedtls_md5; - mbedtls_sha1_context mbedtls_sha1; - - mbedtls_md5_init( &mbedtls_md5 ); - mbedtls_sha1_init( &mbedtls_sha1 ); - - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); - */ - mbedtls_md5_starts( &mbedtls_md5 ); - mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); - mbedtls_md5_update( &mbedtls_md5, dig_signed, dig_signed_len ); - mbedtls_md5_finish( &mbedtls_md5, hash ); - - mbedtls_sha1_starts( &mbedtls_sha1 ); - mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); - mbedtls_sha1_update( &mbedtls_sha1, dig_signed, dig_signed_len ); - mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); - hashlen = 36; - - mbedtls_md5_free( &mbedtls_md5 ); - mbedtls_sha1_free( &mbedtls_sha1 ); + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, + dig_signed, + dig_signed_len ); + if( ret != 0 ) + return( ret ); } else #endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ @@ -2940,32 +3158,12 @@ curve_matching_done: defined(MBEDTLS_SSL_PROTO_TLS1_2) if( md_alg != MBEDTLS_MD_NONE ) { - mbedtls_md_context_t ctx; - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); - - mbedtls_md_init( &ctx ); - - /* Info from md_alg will be used instead */ - hashlen = 0; - - /* - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * }; - */ - if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + dig_signed, + dig_signed_len, + md_alg ); + if( ret != 0 ) return( ret ); - } - - mbedtls_md_starts( &ctx ); - mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); - mbedtls_md_update( &ctx, dig_signed, dig_signed_len ); - mbedtls_md_finish( &ctx, hash ); - mbedtls_md_free( &ctx ); } else #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ @@ -2975,62 +3173,186 @@ curve_matching_done: return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); /* - * Make the signature + * 2.3: Compute and add the signature */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * For TLS 1.2, we need to specify signature and hash algorithm + * explicitly through a prefix to the signature. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * struct { + * SignatureAndHashAlgorithm algorithm; + * opaque signature<0..2^16-1>; + * } DigitallySigned; + * + */ + + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_hash_from_md_alg( md_alg ); + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_sig_from_pk_alg( sig_alg ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_sign_start != NULL ) + { + ret = ssl->conf->f_async_sign_start( ssl, + mbedtls_ssl_own_cert( ssl ), + md_alg, hash, hashlen ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_sign was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_server_key_exchange( ssl, signature_len ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( mbedtls_ssl_own_key( ssl ) == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); } -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - *(p++) = ssl->handshake->sig_alg; - *(p++) = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); - - n += 2; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, - p + 2 , &signature_len, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), + md_alg, hash, hashlen, + ssl->out_msg + ssl->out_msglen + 2, + signature_len, + ssl->conf->f_rng, + ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); return( ret ); } - - *(p++) = (unsigned char)( signature_len >> 8 ); - *(p++) = (unsigned char)( signature_len ); - n += 2; - - MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); - - n += signature_len; } -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - ssl->out_msglen = 4 + n; + return( 0 ); +} + +/* Prepare the ServerKeyExchange message and send it. For ciphersuites + * that do not include a ServerKeyExchange message, do nothing. Either + * way, if successful, move on to the next step in the SSL state + * machine. */ +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t signature_len = 0; +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) + /* Extract static ECDH parameters and abort if ServerKeyExchange + * is not needed. */ + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ssl_get_ecdh_params_from_cert( ssl ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ + + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already prepared the message and there is an ongoing + * signature operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) ); + ret = ssl_resume_server_key_exchange( ssl, &signature_len ); + } + else +#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + { + /* ServerKeyExchange is needed. Prepare the message. */ + ret = ssl_prepare_server_key_exchange( ssl, &signature_len ); + } + + if( ret != 0 ) + { + /* If we're starting to write a new message, set ssl->out_msglen + * to 0. But if we're resuming after an asynchronous message, + * out_msglen is the amount of data written so far and mst be + * preserved. */ + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) ); + else + ssl->out_msglen = 0; + return( ret ); + } + + /* If there is a signature, write its length. + * ssl_prepare_server_key_exchange already wrote the signature + * itself at its proper place in the output buffer. */ +#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) + if( signature_len != 0 ) + { + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 ); + ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", + ssl->out_msg + ssl->out_msglen, + signature_len ); + + /* Skip over the already-written signature */ + ssl->out_msglen += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ + + /* Add header and send. */ ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); - return( 0 ); } @@ -3051,12 +3373,21 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) mbedtls_ssl_send_flight_completed( ssl ); #endif - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); return( 0 ); @@ -3105,33 +3436,59 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char * #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, - const unsigned char *p, - const unsigned char *end, - size_t pms_offset ) + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = ssl->conf->f_async_resume( ssl, + peer_pms, peer_pmslen, peer_pmssize ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret ); + return( ret ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) { int ret; - size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); - unsigned char *pms = ssl->handshake->premaster + pms_offset; - unsigned char ver[2]; - unsigned char fake_pms[48], peer_pms[48]; - unsigned char mask; - size_t i, peer_pmslen; - unsigned int diff; + mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl ); + mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk; + size_t len = mbedtls_pk_get_len( public_key ); - if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already started decoding the message and there is an ongoing + * decryption operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) ); + return( ssl_resume_decrypt_pms( ssl, + peer_pms, peer_pmslen, peer_pmssize ) ); } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /* - * Decrypt the premaster using own private RSA key + * Prepare to decrypt the premaster using own private RSA key */ #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) { + if ( p + 2 > end ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } if( *p++ != ( ( len >> 8 ) & 0xFF ) || *p++ != ( ( len ) & 0xFF ) ) { @@ -3147,30 +3504,120 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); } + /* + * Decrypt the premaster secret + */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_decrypt_start != NULL ) + { + ret = ssl->conf->f_async_decrypt_start( ssl, + mbedtls_ssl_own_cert( ssl ), + p, len ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_decrypt_start was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_decrypt_pms( ssl, + peer_pms, + peer_pmslen, + peer_pmssize ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + ret = mbedtls_pk_decrypt( private_key, p, len, + peer_pms, peer_pmslen, peer_pmssize, + ssl->conf->f_rng, ssl->conf->p_rng ); + return( ret ); +} + +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret; + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + /* In case of a failure in decryption, the decryption may write less than + * 2 bytes of output, but we always read the first two bytes. It doesn't + * matter in the end because diff will be nonzero in that case due to + * peer_pmslen being less than 48, and we only care whether diff is 0. + * But do initialize peer_pms for robustness anyway. This also makes + * memory analyzers happy (don't access uninitialized memory, even + * if it's an unsigned char). */ + peer_pms[0] = peer_pms[1] = ~0; + + ret = ssl_decrypt_encrypted_pms( ssl, p, end, + peer_pms, + &peer_pmslen, + sizeof( peer_pms ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + return( ret ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, - ssl->handshake->max_minor_ver, - ssl->conf->transport, ver ); + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* Avoid data-dependent branches while checking for invalid + * padding, to protect against timing-based Bleichenbacher-type + * attacks. */ + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif /* * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding * must not cause the connection to end immediately; instead, send a * bad_record_mac later in the handshake. - * Also, avoid data-dependant branches here to protect against - * timing-based variants. + * To protect against timing-based variants of the attack, we must + * not have any branch that depends on whether the decryption was + * successful. In particular, always generate the fake premaster secret, + * regardless of whether it will ultimately influence the output or not. */ ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); if( ret != 0 ) + { + /* It's ok to abort on an RNG failure, since this does not reveal + * anything about the RSA decryption. */ return( ret ); - - ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, - peer_pms, &peer_pmslen, - sizeof( peer_pms ), - ssl->conf->f_rng, ssl->conf->p_rng ); - - diff = (unsigned int) ret; - diff |= peer_pmslen ^ 48; - diff |= peer_pms[0] ^ ver[0]; - diff |= peer_pms[1] ^ ver[1]; + } #if defined(MBEDTLS_SSL_DEBUG_ALL) if( diff != 0 ) @@ -3185,18 +3632,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, } ssl->handshake->pmslen = 48; - /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - + /* Set pms to either the true or the fake PMS, without + * data-dependent branches. */ for( i = 0; i < ssl->handshake->pmslen; i++ ) pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); @@ -3223,7 +3660,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha /* * Receive client pre-shared key identity name */ - if( *p + 2 > end ) + if( end - *p < 2 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); @@ -3232,7 +3669,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha n = ( (*p)[0] << 8 ) | (*p)[1]; *p += 2; - if( n < 1 || n > 65535 || *p + n > end ) + if( n < 1 || n > 65535 || n > (size_t) ( end - *p ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); @@ -3257,13 +3694,8 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) { MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ) ) != 0 ) - { - return( ret ); - } - + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); } @@ -3283,7 +3715,21 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) + if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) && + ( ssl->handshake->async_in_progress != 0 ) ) + { + /* We've already read a record and there is an asynchronous + * operation in progress to decrypt it. So skip reading the + * record. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) ); + } + else +#endif + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -3349,7 +3795,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); } - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, @@ -3361,7 +3808,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); } - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || @@ -3395,6 +3843,19 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ssl->handshake->async_in_progress != 0 ) + { + /* There is an asynchronous operation in progress to + * decrypt the encrypted premaster secret, so skip + * directly to resuming this operation. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) ); + /* Update p to skip the PSK identity. ssl_parse_encrypted_pms + * won't actually use it, but maintain p anyway for robustness. */ + p += ssl->conf->psk_identity_len + 2; + } + else +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); @@ -3461,7 +3922,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); } - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, ciphersuite_info->key_exchange ) ) != 0 ) @@ -3531,7 +3993,8 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) { - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); @@ -3561,7 +4024,8 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) mbedtls_pk_type_t pk_alg; #endif mbedtls_md_type_t md_alg; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); @@ -3578,21 +4042,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) } /* Read the message without adding it to the checksum */ - do { - - if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); - return( ret ); - } - - ret = mbedtls_ssl_handle_message_type( ssl ); - - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); - + ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ ); if( 0 != ret ) { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret ); return( ret ); } @@ -3758,7 +4211,7 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, ssl->session_negotiate, ssl->out_msg + 10, - ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, &tlen, &lifetime ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); @@ -3781,9 +4234,9 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) */ ssl->handshake->new_session_ticket = 0; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -3812,10 +4265,10 @@ int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) return( ret ); } -#endif +#endif /* MBEDTLS_SSL_PROTO_DTLS */ switch( ssl->state ) { diff --git a/Externals/mbedtls/library/ssl_ticket.c b/Externals/mbedtls/library/ssl_ticket.c index 4d9116d214..8492c19a8c 100644 --- a/Externals/mbedtls/library/ssl_ticket.c +++ b/Externals/mbedtls/library/ssl_ticket.c @@ -36,14 +36,10 @@ #endif #include "mbedtls/ssl_ticket.h" +#include "mbedtls/platform_util.h" #include -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Initialze context */ @@ -83,7 +79,7 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, mbedtls_cipher_get_key_bitlen( &key->ctx ), MBEDTLS_ENCRYPT ); - mbedtls_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); return( ret ); } @@ -101,7 +97,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) uint32_t current_time = (uint32_t) mbedtls_time( NULL ); uint32_t key_time = ctx->keys[ctx->active].generation_time; - if( current_time > key_time && + if( current_time >= key_time && current_time - key_time < ctx->ticket_lifetime ) { return( 0 ); @@ -192,9 +188,9 @@ static int ssl_save_session( const mbedtls_ssl_session *session, if( left < 3 + cert_len ) return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - *p++ = (unsigned char)( cert_len >> 16 & 0xFF ); - *p++ = (unsigned char)( cert_len >> 8 & 0xFF ); - *p++ = (unsigned char)( cert_len & 0xFF ); + *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len ) & 0xFF ); if( session->peer_cert != NULL ) memcpy( p, session->peer_cert->raw.p, cert_len ); @@ -219,14 +215,14 @@ static int ssl_load_session( mbedtls_ssl_session *session, size_t cert_len; #endif /* MBEDTLS_X509_CRT_PARSE_C */ - if( p + sizeof( mbedtls_ssl_session ) > end ) + if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); memcpy( session, p, sizeof( mbedtls_ssl_session ) ); p += sizeof( mbedtls_ssl_session ); #if defined(MBEDTLS_X509_CRT_PARSE_C) - if( p + 3 > end ) + if( 3 > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; @@ -240,7 +236,7 @@ static int ssl_load_session( mbedtls_ssl_session *session, { int ret; - if( p + cert_len > end ) + if( cert_len > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); @@ -251,7 +247,7 @@ static int ssl_load_session( mbedtls_ssl_session *session, mbedtls_x509_crt_init( session->peer_cert ); if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, - p, cert_len ) ) != 0 ) + p, cert_len ) ) != 0 ) { mbedtls_x509_crt_free( session->peer_cert ); mbedtls_free( session->peer_cert ); @@ -483,7 +479,7 @@ void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) mbedtls_mutex_free( &ctx->mutex ); #endif - mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); } #endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/Externals/mbedtls/library/ssl_tls.c b/Externals/mbedtls/library/ssl_tls.c index 84a04ae53f..38690fa664 100644 --- a/Externals/mbedtls/library/ssl_tls.c +++ b/Externals/mbedtls/library/ssl_tls.c @@ -46,6 +46,7 @@ #include "mbedtls/debug.h" #include "mbedtls/ssl.h" #include "mbedtls/ssl_internal.h" +#include "mbedtls/platform_util.h" #include @@ -53,10 +54,8 @@ #include "mbedtls/oid.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); /* Length of the "epoch" field in the record header */ static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) @@ -100,7 +99,101 @@ static int ssl_check_timer( mbedtls_ssl_context *ssl ) return( 0 ); } +static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); +static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); + +#define SSL_DONT_FORCE_FLUSH 0 +#define SSL_FORCE_FLUSH 1 + #if defined(MBEDTLS_SSL_PROTO_DTLS) + +/* Forward declarations for functions related to message buffering. */ +static void ssl_buffering_free( mbedtls_ssl_context *ssl ); +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ); +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_buffer_message( mbedtls_ssl_context *ssl ); +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl ); +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); + +static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); +static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) +{ + size_t mtu = ssl_get_current_mtu( ssl ); + + if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN ) + return( mtu ); + + return( MBEDTLS_SSL_OUT_BUFFER_LEN ); +} + +static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) +{ + size_t const bytes_written = ssl->out_left; + size_t const mtu = ssl_get_maximum_datagram_size( ssl ); + + /* Double-check that the write-index hasn't gone + * past what we can transmit in a single datagram. */ + if( bytes_written > mtu ) + { + /* Should never happen... */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int) ( mtu - bytes_written ) ); +} + +static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) +{ + int ret; + size_t remaining, expansion; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; + + /* By the standard (RFC 6066 Sect. 4), the MFL extension + * only limits the maximum record payload size, so in theory + * we would be allowed to pack multiple records of payload size + * MFL into a single datagram. However, this would mean that there's + * no way to explicitly communicate MTU restrictions to the peer. + * + * The following reduction of max_len makes sure that we never + * write datagrams larger than MFL + Record Expansion Overhead. + */ + if( max_len <= ssl->out_left ) + return( 0 ); + + max_len -= ssl->out_left; +#endif + + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + remaining = (size_t) ret; + + ret = mbedtls_ssl_get_record_expansion( ssl ); + if( ret < 0 ) + return( ret ); + expansion = (size_t) ret; + + if( remaining <= expansion ) + return( 0 ); + + remaining -= expansion; + if( remaining >= max_len ) + remaining = max_len; + + return( (int) remaining ); +} + /* * Double the retransmit timeout value, within the allowed range, * returning -1 if the maximum value has already been reached. @@ -112,6 +205,18 @@ static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) return( -1 ); + /* Implement the final paragraph of RFC 6347 section 4.1.1.1 + * in the following way: after the initial transmission and a first + * retransmission, back off to a temporary estimated MTU of 508 bytes. + * This value is guaranteed to be deliverable (if not guaranteed to be + * delivered) of any compliant IPv4 (and IPv6) network, and should work + * on most non-IP stacks too. */ + if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) + { + ssl->handshake->mtu = 508; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); + } + new_timeout = 2 * ssl->handshake->retransmit_timeout; /* Avoid arithmetic overflow and range overflow */ @@ -145,14 +250,24 @@ static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) * } MaxFragmentLength; * and we add 0 -> extension unused */ -static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = +static unsigned int ssl_mfl_code_to_length( int mfl ) { - MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ - 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ - 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ - 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ - 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ -}; + switch( mfl ) + { + case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + case MBEDTLS_SSL_MAX_FRAG_LEN_512: + return 512; + case MBEDTLS_SSL_MAX_FRAG_LEN_1024: + return 1024; + case MBEDTLS_SSL_MAX_FRAG_LEN_2048: + return 2048; + case MBEDTLS_SSL_MAX_FRAG_LEN_4096: + return 4096; + default: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + } +} #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_CLI_C) @@ -221,6 +336,7 @@ static int ssl3_prf( const unsigned char *secret, size_t slen, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen ) { + int ret = 0; size_t i; mbedtls_md5_context md5; mbedtls_sha1_context sha1; @@ -243,25 +359,35 @@ static int ssl3_prf( const unsigned char *secret, size_t slen, { memset( padding, (unsigned char) ('A' + i), 1 + i ); - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, padding, 1 + i ); - mbedtls_sha1_update( &sha1, secret, slen ); - mbedtls_sha1_update( &sha1, random, rlen ); - mbedtls_sha1_finish( &sha1, sha1sum ); + if( ( ret = mbedtls_sha1_starts_ret( &sha1 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, padding, 1 + i ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, random, rlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_finish_ret( &sha1, sha1sum ) ) != 0 ) + goto exit; - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, secret, slen ); - mbedtls_md5_update( &md5, sha1sum, 20 ); - mbedtls_md5_finish( &md5, dstbuf + i * 16 ); + if( ( ret = mbedtls_md5_starts_ret( &md5 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, sha1sum, 20 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5, dstbuf + i * 16 ) ) != 0 ) + goto exit; } +exit: mbedtls_md5_free( &md5 ); mbedtls_sha1_free( &sha1 ); - mbedtls_zeroize( padding, sizeof( padding ) ); - mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + mbedtls_platform_zeroize( padding, sizeof( padding ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); - return( 0 ); + return( ret ); } #endif /* MBEDTLS_SSL_PROTO_SSL3 */ @@ -356,8 +482,8 @@ static int tls1_prf( const unsigned char *secret, size_t slen, mbedtls_md_free( &md_ctx ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( h_i, sizeof( h_i ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); return( 0 ); } @@ -421,8 +547,8 @@ static int tls_prf_generic( mbedtls_md_type_t md_type, mbedtls_md_free( &md_ctx ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( h_i, sizeof( h_i ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); return( 0 ); } @@ -490,6 +616,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) unsigned char *key2; unsigned char *mac_enc; unsigned char *mac_dec; + size_t mac_key_len; size_t iv_copy_len; const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; @@ -630,7 +757,8 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) return( ret ); } - mbedtls_zeroize( handshake->premaster, sizeof(handshake->premaster) ); + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); } else MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); @@ -641,7 +769,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) memcpy( tmp, handshake->randbytes, 64 ); memcpy( handshake->randbytes, tmp + 32, 32 ); memcpy( handshake->randbytes + 32, tmp, 32 ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); /* * SSLv3: @@ -669,7 +797,8 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); - mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); + mbedtls_platform_zeroize( handshake->randbytes, + sizeof( handshake->randbytes ) ); /* * Determine the appropriate key, IV and MAC length. @@ -678,17 +807,32 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) transform->keylen = cipher_info->key_bitlen / 8; if( cipher_info->mode == MBEDTLS_MODE_GCM || - cipher_info->mode == MBEDTLS_MODE_CCM ) + cipher_info->mode == MBEDTLS_MODE_CCM || + cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) { + size_t taglen, explicit_ivlen; + transform->maclen = 0; + mac_key_len = 0; + /* All modes haves 96-bit IVs; + * GCM and CCM has 4 implicit and 8 explicit bytes + * ChachaPoly has all 12 bytes implicit + */ transform->ivlen = 12; - transform->fixed_ivlen = 4; + if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + transform->fixed_ivlen = 12; + else + transform->fixed_ivlen = 4; - /* Minimum length is expicit IV + tag */ - transform->minlen = transform->ivlen - transform->fixed_ivlen - + ( transform->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); + /* All modes have 128-bit tags, except CCM_8 (ciphersuite flag) */ + taglen = transform->ciphersuite_info->flags & + MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + + /* Minimum length of encrypted record */ + explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + transform->minlen = explicit_ivlen + taglen; } else { @@ -701,7 +845,8 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) } /* Get MAC length */ - transform->maclen = mbedtls_md_get_size( md_info ); + mac_key_len = mbedtls_md_get_size( md_info ); + transform->maclen = mac_key_len; #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) /* @@ -710,7 +855,16 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) * so we only need to adjust the length here. */ if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + { transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + /* Fall back to old, non-compliant version of the truncated + * HMAC implementation which also truncates the key + * (Mbed TLS versions from 1.3 to 2.6.0) */ + mac_key_len = transform->maclen; +#endif + } #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ /* IV length */ @@ -772,11 +926,11 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_CLI_C) if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) { - key1 = keyblk + transform->maclen * 2; - key2 = keyblk + transform->maclen * 2 + transform->keylen; + key1 = keyblk + mac_key_len * 2; + key2 = keyblk + mac_key_len * 2 + transform->keylen; mac_enc = keyblk; - mac_dec = keyblk + transform->maclen; + mac_dec = keyblk + mac_key_len; /* * This is not used in TLS v1.1. @@ -792,10 +946,10 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_SRV_C) if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) { - key1 = keyblk + transform->maclen * 2 + transform->keylen; - key2 = keyblk + transform->maclen * 2; + key1 = keyblk + mac_key_len * 2 + transform->keylen; + key2 = keyblk + mac_key_len * 2; - mac_enc = keyblk + transform->maclen; + mac_enc = keyblk + mac_key_len; mac_dec = keyblk; /* @@ -817,14 +971,14 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_PROTO_SSL3) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { - if( transform->maclen > sizeof transform->mac_enc ) + if( mac_key_len > sizeof transform->mac_enc ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - memcpy( transform->mac_enc, mac_enc, transform->maclen ); - memcpy( transform->mac_dec, mac_dec, transform->maclen ); + memcpy( transform->mac_enc, mac_enc, mac_key_len ); + memcpy( transform->mac_dec, mac_dec, mac_key_len ); } else #endif /* MBEDTLS_SSL_PROTO_SSL3 */ @@ -832,8 +986,13 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) { - mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen ); - mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen ); + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if( mac_key_len != 0 ) + { + mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len ); + mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); + } } else #endif @@ -853,7 +1012,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) transform->iv_enc, transform->iv_dec, iv_copy_len, mac_enc, mac_dec, - transform->maclen ) ) != 0 ) + mac_key_len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); @@ -866,7 +1025,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) { ssl->conf->f_export_keys( ssl->conf->p_export_keys, session->master, keyblk, - transform->maclen, transform->keylen, + mac_key_len, transform->keylen, iv_copy_len ); } #endif @@ -920,7 +1079,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_CIPHER_MODE_CBC */ - mbedtls_zeroize( keyblk, sizeof( keyblk ) ); + mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) ); #if defined(MBEDTLS_ZLIB_SUPPORT) // Initialize compression @@ -930,11 +1089,11 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) if( ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); - ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); if( ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - MBEDTLS_SSL_BUFFER_LEN ) ); + MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } } @@ -978,25 +1137,25 @@ void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) memset( pad_1, 0x36, 48 ); memset( pad_2, 0x5C, 48 ); - mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); - mbedtls_md5_update( &md5, pad_1, 48 ); - mbedtls_md5_finish( &md5, hash ); + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_1, 48 ); + mbedtls_md5_finish_ret( &md5, hash ); - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); - mbedtls_md5_update( &md5, pad_2, 48 ); - mbedtls_md5_update( &md5, hash, 16 ); - mbedtls_md5_finish( &md5, hash ); + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_2, 48 ); + mbedtls_md5_update_ret( &md5, hash, 16 ); + mbedtls_md5_finish_ret( &md5, hash ); - mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); - mbedtls_sha1_update( &sha1, pad_1, 40 ); - mbedtls_sha1_finish( &sha1, hash + 16 ); + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_1, 40 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); - mbedtls_sha1_update( &sha1, pad_2, 40 ); - mbedtls_sha1_update( &sha1, hash + 16, 20 ); - mbedtls_sha1_finish( &sha1, hash + 16 ); + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_2, 40 ); + mbedtls_sha1_update_ret( &sha1, hash + 16, 20 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); @@ -1022,8 +1181,8 @@ void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - mbedtls_md5_finish( &md5, hash ); - mbedtls_sha1_finish( &sha1, hash + 16 ); + mbedtls_md5_finish_ret( &md5, hash ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); @@ -1046,7 +1205,7 @@ void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); - mbedtls_sha256_finish( &sha256, hash ); + mbedtls_sha256_finish_ret( &sha256, hash ); MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); @@ -1067,7 +1226,7 @@ void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48 MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); - mbedtls_sha512_finish( &sha512, hash ); + mbedtls_sha512_finish_ret( &sha512, hash ); MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); @@ -1125,6 +1284,9 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch * other_secret already set by the ClientKeyExchange message, * and is 48 bytes long */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + *p++ = 0; *p++ = 48; p += 48; @@ -1171,7 +1333,8 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch *(p++) = (unsigned char)( zlen ); p += zlen; - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ @@ -1203,9 +1366,12 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch /* * SSLv3.0 MAC functions */ -static void ssl_mac( mbedtls_md_context_t *md_ctx, unsigned char *secret, - unsigned char *buf, size_t len, - unsigned char *ctr, int type ) +#define SSL_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ +static void ssl_mac( mbedtls_md_context_t *md_ctx, + const unsigned char *secret, + const unsigned char *buf, size_t len, + const unsigned char *ctr, int type, + unsigned char out[SSL_MAC_MAX_BYTES] ) { unsigned char header[11]; unsigned char padding[48]; @@ -1230,23 +1396,44 @@ static void ssl_mac( mbedtls_md_context_t *md_ctx, unsigned char *secret, mbedtls_md_update( md_ctx, padding, padlen ); mbedtls_md_update( md_ctx, header, 11 ); mbedtls_md_update( md_ctx, buf, len ); - mbedtls_md_finish( md_ctx, buf + len ); + mbedtls_md_finish( md_ctx, out ); memset( padding, 0x5C, padlen ); mbedtls_md_starts( md_ctx ); mbedtls_md_update( md_ctx, secret, md_size ); mbedtls_md_update( md_ctx, padding, padlen ); - mbedtls_md_update( md_ctx, buf + len, md_size ); - mbedtls_md_finish( md_ctx, buf + len ); + mbedtls_md_update( md_ctx, out, md_size ); + mbedtls_md_finish( md_ctx, out ); } #endif /* MBEDTLS_SSL_PROTO_SSL3 */ #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ ( defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) ) + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C)) ) #define SSL_SOME_MODES_USE_MAC #endif +/* The function below is only used in the Lucky 13 counter-measure in + * ssl_decrypt_buf(). These are the defines that guard the call site. */ +#if defined(SSL_SOME_MODES_USE_MAC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +/* This function makes sure every byte in the memory region is accessed + * (in ascending addresses order) */ +static void ssl_read_memory( unsigned char *p, size_t len ) +{ + unsigned char acc = 0; + volatile unsigned char force; + + for( ; len != 0; p++, len-- ) + acc ^= *p; + + force = acc; + (void) force; +} +#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */ + /* * Encryption/decryption functions */ @@ -1282,10 +1469,15 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_PROTO_SSL3) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { + unsigned char mac[SSL_MAC_MAX_BYTES]; + ssl_mac( &ssl->transform_out->md_ctx_enc, ssl->transform_out->mac_enc, ssl->out_msg, ssl->out_msglen, - ssl->out_ctr, ssl->out_msgtype ); + ssl->out_ctr, ssl->out_msgtype, + mac ); + + memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); } else #endif @@ -1293,14 +1485,17 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 ); mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 ); mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 ); mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_msg, ssl->out_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, - ssl->out_msg + ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac ); mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + memcpy( ssl->out_msg + ssl->out_msglen, mac, ssl->transform_out->maclen ); } else #endif @@ -1349,17 +1544,26 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) { int ret; size_t enc_msglen, olen; unsigned char *enc_msg; unsigned char add_data[13]; - unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & + unsigned char iv[12]; + mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned char taglen = transform->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + size_t explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + /* + * Prepare additional authenticated data + */ memcpy( add_data, ssl->out_ctr, 8 ); add_data[8] = ssl->out_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, @@ -1367,44 +1571,57 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; add_data[12] = ssl->out_msglen & 0xFF; - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); /* * Generate IV */ - if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (=seqnum) */ + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, ssl->out_ctr, 8 ); + memcpy( ssl->out_iv, ssl->out_ctr, 8 ); + + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_enc, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= ssl->out_ctr[i]; + } + else { /* Reminder if we ever add an AEAD mode with a different size */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, - ssl->out_ctr, 8 ); - memcpy( ssl->out_iv, ssl->out_ctr, 8 ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, - ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", + iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", + ssl->out_iv, explicit_ivlen ); /* - * Fix pointer positions and message length with added IV + * Fix message length with added IV */ enc_msg = ssl->out_msg; enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; + ssl->out_msglen += explicit_ivlen; MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); + "including 0 bytes of padding", + ssl->out_msglen ) ); /* * Encrypt and authenticate */ - if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, + if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc, + iv, transform->ivlen, add_data, 13, enc_msg, enc_msglen, enc_msg, &olen, @@ -1428,7 +1645,7 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) else #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ #if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) if( mode == MBEDTLS_MODE_CBC ) { int ret; @@ -1511,6 +1728,8 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if( auth_done == 0 ) { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + /* * MAC(MAC_write_key, seq_num + * TLSCipherText.type + @@ -1533,10 +1752,12 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_iv, ssl->out_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, - ssl->out_iv + ssl->out_msglen ); + mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, mac ); mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + memcpy( ssl->out_iv + ssl->out_msglen, mac, + ssl->transform_out->maclen ); + ssl->out_msglen += ssl->transform_out->maclen; auth_done++; } @@ -1544,7 +1765,7 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); @@ -1562,11 +1783,8 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) return( 0 ); } -#define SSL_MAX_MAC_SIZE 48 - static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) { - size_t i; mbedtls_cipher_mode_t mode; int auth_done = 0; #if defined(SSL_SOME_MODES_USE_MAC) @@ -1616,20 +1834,27 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) { int ret; size_t dec_msglen, olen; unsigned char *dec_msg; unsigned char *dec_msg_result; unsigned char add_data[13]; - unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & + unsigned char iv[12]; + mbedtls_ssl_transform *transform = ssl->transform_in; + unsigned char taglen = transform->ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; - size_t explicit_iv_len = ssl->transform_in->ivlen - - ssl->transform_in->fixed_ivlen; + size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen; + /* + * Compute and update sizes + */ if( ssl->in_msglen < explicit_iv_len + taglen ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " @@ -1643,6 +1868,9 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) dec_msg_result = ssl->in_msg; ssl->in_msglen = dec_msglen; + /* + * Prepare additional authenticated data + */ memcpy( add_data, ssl->in_ctr, 8 ); add_data[8] = ssl->in_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, @@ -1650,23 +1878,43 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; add_data[12] = ssl->in_msglen & 0xFF; - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data for AEAD", add_data, 13 ); - memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, - ssl->in_iv, - ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); + /* + * Prepare IV + */ + if( transform->ivlen == 12 && transform->fixed_ivlen == 4 ) + { + /* GCM and CCM: fixed || explicit (transmitted) */ + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + memcpy( iv + transform->fixed_ivlen, ssl->in_iv, 8 ); - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, - ssl->transform_in->ivlen ); + } + else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 ) + { + /* ChachaPoly: fixed XOR sequence number */ + unsigned char i; + + memcpy( iv, transform->iv_dec, transform->fixed_ivlen ); + + for( i = 0; i < 8; i++ ) + iv[i+4] ^= ssl->in_ctr[i]; + } + else + { + /* Reminder if we ever add an AEAD mode with a different size */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); /* * Decrypt and authenticate */ if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, + iv, transform->ivlen, add_data, 13, dec_msg, dec_msglen, dec_msg_result, &olen, @@ -1690,7 +1938,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) else #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ #if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) + ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) if( mode == MBEDTLS_MODE_CBC ) { /* @@ -1731,7 +1979,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) { - unsigned char computed_mac[SSL_MAX_MAC_SIZE]; + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; unsigned char pseudo_hdr[13]; MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); @@ -1749,16 +1997,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_iv, ssl->in_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, ssl->transform_in->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", computed_mac, + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); - if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac, - ssl->transform_in->maclen ) != 0 ) + if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, mac_expect, + ssl->transform_in->maclen ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); @@ -1784,6 +2032,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) */ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) { + unsigned char i; dec_msglen -= ssl->transform_in->ivlen; ssl->in_msglen -= ssl->transform_in->ivlen; @@ -1857,27 +2106,28 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) * and fake check up to 256 bytes of padding */ size_t pad_count = 0, real_count = 1; - size_t padding_idx = ssl->in_msglen - padlen - 1; + size_t padding_idx = ssl->in_msglen - padlen; + size_t i; /* * Padding is guaranteed to be incorrect if: - * 1. padlen >= ssl->in_msglen + * 1. padlen > ssl->in_msglen * - * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN + + * 2. padding_idx > MBEDTLS_SSL_IN_CONTENT_LEN + * ssl->transform_in->maclen * * In both cases we reset padding_idx to a safe value (0) to * prevent out-of-buffer reads. */ - correct &= ( ssl->in_msglen >= padlen + 1 ); - correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + + correct &= ( padlen <= ssl->in_msglen ); + correct &= ( padding_idx <= MBEDTLS_SSL_IN_CONTENT_LEN + ssl->transform_in->maclen ); padding_idx *= correct; - for( i = 1; i <= 256; i++ ) + for( i = 0; i < 256; i++ ) { - real_count &= ( i <= padlen ); + real_count &= ( i < padlen ); pad_count += real_count * ( ssl->in_msg[padding_idx + i] == padlen - 1 ); } @@ -1902,14 +2152,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ + ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } +#if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", ssl->in_msg, ssl->in_msglen ); +#endif /* * Authenticate if not done yet. @@ -1918,22 +2170,21 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) #if defined(SSL_SOME_MODES_USE_MAC) if( auth_done == 0 ) { - unsigned char tmp[SSL_MAX_MAC_SIZE]; + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; ssl->in_msglen -= ssl->transform_in->maclen; ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); - memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); - #if defined(MBEDTLS_SSL_PROTO_SSL3) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { ssl_mac( &ssl->transform_in->md_ctx_dec, ssl->transform_in->mac_dec, ssl->in_msg, ssl->in_msglen, - ssl->in_ctr, ssl->in_msgtype ); + ssl->in_ctr, ssl->in_msgtype, + mac_expect ); } else #endif /* MBEDTLS_SSL_PROTO_SSL3 */ @@ -1943,20 +2194,69 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) { /* * Process MAC and always update for padlen afterwards to make - * total time independent of padlen - * - * extra_run compensates MAC check for padlen + * total time independent of padlen. * * Known timing attacks: * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) * - * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values - * correctly. (We round down instead of up, so -56 is the correct - * value for our calculations instead of -55) + * To compensate for different timings for the MAC calculation + * depending on how much padding was removed (which is determined + * by padlen), process extra_run more blocks through the hash + * function. + * + * The formula in the paper is + * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 ) + * where L1 is the size of the header plus the decrypted message + * plus CBC padding and L2 is the size of the header plus the + * decrypted message. This is for an underlying hash function + * with 64-byte blocks. + * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values + * correctly. We round down instead of up, so -56 is the correct + * value for our calculations instead of -55. + * + * Repeat the formula rather than defining a block_size variable. + * This avoids requiring division by a variable at runtime + * (which would be marginally less efficient and would require + * linking an extra division function in some builds). */ size_t j, extra_run = 0; - extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - - ( 13 + ssl->in_msglen + 8 ) / 64; + + /* + * The next two sizes are the minimum and maximum values of + * in_msglen over all padlen values. + * + * They're independent of padlen, since we previously did + * in_msglen -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = ssl->in_msglen + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + switch( ssl->transform_in->ciphersuite_info->mac ) + { +#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \ + defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_MD5: + case MBEDTLS_MD_SHA1: + case MBEDTLS_MD_SHA256: + /* 8 bytes of message size, 64-byte compression blocks */ + extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - + ( 13 + ssl->in_msglen + 8 ) / 64; + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + /* 16 bytes of message size, 128-byte compression blocks */ + extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 - + ( 13 + ssl->in_msglen + 16 ) / 128; + break; +#endif + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } extra_run &= correct * 0xFF; @@ -1965,13 +2265,25 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, ssl->in_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, - ssl->in_msg + ssl->in_msglen ); - /* Call mbedtls_md_process at least once due to cache attacks */ + /* Make sure we access everything even when padlen > 0. This + * makes the synchronisation requirements for just-in-time + * Prime+Probe attacks much tighter and hopefully impractical. */ + ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen ); + mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); + + /* Call mbedtls_md_process at least once due to cache attacks + * that observe whether md_process() was called of not */ for( j = 0; j < extra_run + 1; j++ ) mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); + + /* Make sure we access all the memory that could contain the MAC, + * before we check it in the next code block. This makes the + * synchronisation requirements for just-in-time Prime+Probe + * attacks much tighter and hopefully impractical. */ + ssl_read_memory( ssl->in_msg + min_len, + max_len - min_len + ssl->transform_in->maclen ); } else #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ @@ -1981,12 +2293,14 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, - ssl->transform_in->maclen ); +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); +#endif - if( mbedtls_ssl_safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen, - ssl->transform_in->maclen ) != 0 ) + if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect, + ssl->transform_in->maclen ) != 0 ) { #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); @@ -1994,13 +2308,13 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) correct = 0; } auth_done++; - - /* - * Finally check the correct flag - */ - if( correct == 0 ) - return( MBEDTLS_ERR_SSL_INVALID_MAC ); } + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); #endif /* SSL_SOME_MODES_USE_MAC */ /* Make extra sure authentication was performed, exactly once */ @@ -2012,6 +2326,16 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) if( ssl->in_msglen == 0 ) { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + ssl->nb_zero++; /* @@ -2036,6 +2360,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) else #endif { + unsigned char i; for( i = 8; i > ssl_ep_len( ssl ); i-- ) if( ++ssl->in_ctr[i - 1] != 0 ) break; @@ -2065,6 +2390,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) { int ret; unsigned char *msg_post = ssl->out_msg; + ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; size_t len_pre = ssl->out_msglen; unsigned char *msg_pre = ssl->compress_buf; @@ -2084,7 +2410,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) ssl->transform_out->ctx_deflate.next_in = msg_pre; ssl->transform_out->ctx_deflate.avail_in = len_pre; ssl->transform_out->ctx_deflate.next_out = msg_post; - ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN; + ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written; ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); if( ret != Z_OK ) @@ -2093,8 +2419,8 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); } - ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN - - ssl->transform_out->ctx_deflate.avail_out; + ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN - + ssl->transform_out->ctx_deflate.avail_out - bytes_written; MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", ssl->out_msglen ) ); @@ -2111,6 +2437,7 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) { int ret; unsigned char *msg_post = ssl->in_msg; + ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; size_t len_pre = ssl->in_msglen; unsigned char *msg_pre = ssl->compress_buf; @@ -2130,7 +2457,8 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) ssl->transform_in->ctx_inflate.next_in = msg_pre; ssl->transform_in->ctx_inflate.avail_in = len_pre; ssl->transform_in->ctx_inflate.next_out = msg_post; - ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_MAX_CONTENT_LEN; + ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN - + header_bytes; ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); if( ret != Z_OK ) @@ -2139,8 +2467,8 @@ static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); } - ssl->in_msglen = MBEDTLS_SSL_MAX_CONTENT_LEN - - ssl->transform_in->ctx_inflate.avail_out; + ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN - + ssl->transform_in->ctx_inflate.avail_out - header_bytes; MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", ssl->in_msglen ) ); @@ -2214,7 +2542,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); @@ -2294,10 +2622,13 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) * that will end up being dropped. */ if( ssl_check_timer( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); ret = MBEDTLS_ERR_SSL_TIMEOUT; + } else { - len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); + len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) timeout = ssl->handshake->retransmit_timeout; @@ -2396,6 +2727,14 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) if( ret < 0 ) return( ret ); + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_recv returned %d bytes but only %lu were requested", + ret, (unsigned long)len ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->in_left += ret; } } @@ -2411,7 +2750,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) { int ret; - unsigned char *buf, i; + unsigned char *buf; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); @@ -2434,8 +2773,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); - buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) + - ssl->out_msglen - ssl->out_left; + buf = ssl->out_hdr - ssl->out_left; ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); @@ -2443,19 +2781,28 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) if( ret <= 0 ) return( ret ); + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_send returned %d bytes but only %lu bytes were sent", + ret, (unsigned long)ssl->out_left ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->out_left -= ret; } - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + ssl->out_hdr = ssl->out_buf; } + else +#endif + { + ssl->out_hdr = ssl->out_buf + 8; + } + ssl_update_out_pointers( ssl, ssl->transform_out ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); @@ -2472,6 +2819,9 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) static int ssl_flight_append( mbedtls_ssl_context *ssl ) { mbedtls_ssl_flight_item *msg; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", + ssl->out_msg, ssl->out_msglen ); /* Allocate space for current message */ if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) @@ -2505,6 +2855,7 @@ static int ssl_flight_append( mbedtls_ssl_context *ssl ) cur->next = msg; } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); return( 0 ); } @@ -2553,19 +2904,12 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) ssl->handshake->alt_transform_out = tmp_transform; /* Swap epoch + sequence_number */ - memcpy( tmp_out_ctr, ssl->out_ctr, 8 ); - memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); + memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); /* Adjust to the newly activated transform */ - if( ssl->transform_out != NULL && - ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; + ssl_update_out_pointers( ssl, ssl->transform_out ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_activate != NULL ) @@ -2581,20 +2925,38 @@ static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) /* * Retransmit the current flight of messages. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + ret = mbedtls_ssl_flight_transmit( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( ret ); +} + +/* + * Transmit or retransmit the current flight of messages. * * Need to remember the current message in case flush_output returns * WANT_WRITE, causing us to exit this function and come back later. * This function must be called until state is no longer SENDING. */ -int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + int ret; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); ssl->handshake->cur_msg = ssl->handshake->flight; + ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; ssl_swap_epochs( ssl ); ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; @@ -2602,33 +2964,129 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) while( ssl->handshake->cur_msg != NULL ) { - int ret; - mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg; + size_t max_frag_len; + const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + + int const is_finished = + ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); + + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; /* Swap epochs before sending Finished: we can't do it after * sending ChangeCipherSpec, in case write returns WANT_READ. * Must be done before copying, may change out_msg pointer */ - if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && - cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) + if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); ssl_swap_epochs( ssl ); } - memcpy( ssl->out_msg, cur->p, cur->len ); - ssl->out_msglen = cur->len; - ssl->out_msgtype = cur->type; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + max_frag_len = (size_t) ret; - ssl->handshake->cur_msg = cur->next; + /* CCS is copied as is, while HS messages may need fragmentation */ + if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( max_frag_len == 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); - MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 ); + continue; + } - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur->len; + } + else + { + const unsigned char * const p = ssl->handshake->cur_msg_p; + const size_t hs_len = cur->len - 12; + const size_t frag_off = p - ( cur->p + 12 ); + const size_t rem_len = hs_len - frag_off; + size_t cur_hs_frag_len, max_hs_frag_len; + + if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) + { + if( is_finished ) + ssl_swap_epochs( ssl ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + max_hs_frag_len = max_frag_len - 12; + + cur_hs_frag_len = rem_len > max_hs_frag_len ? + max_hs_frag_len : rem_len; + + if( frag_off == 0 && cur_hs_frag_len != hs_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", + (unsigned) cur_hs_frag_len, + (unsigned) max_hs_frag_len ) ); + } + + /* Messages are stored with handshake headers as if not fragmented, + * copy beginning of headers then fill fragmentation fields. + * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ + memcpy( ssl->out_msg, cur->p, 6 ); + + ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff ); + ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff ); + ssl->out_msg[8] = ( ( frag_off ) & 0xff ); + + ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff ); + ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff ); + ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); + + /* Copy the handshake message content and set records fields */ + memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); + ssl->out_msglen = cur_hs_frag_len + 12; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur_hs_frag_len; + } + + /* If done with the current message move to the next one if any */ + if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) + { + if( cur->next != NULL ) + { + ssl->handshake->cur_msg = cur->next; + ssl->handshake->cur_msg_p = cur->next->p + 12; + } + else + { + ssl->handshake->cur_msg = NULL; + ssl->handshake->cur_msg_p = NULL; + } + } + + /* Actually send the message out */ + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } } + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + /* Update state and set timer */ if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; else @@ -2637,7 +3095,7 @@ int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); return( 0 ); } @@ -2655,6 +3113,12 @@ void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) /* The next incoming flight will start with this msg_seq */ ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + /* We don't want to remember CCS's across flight boundaries. */ + ssl->handshake->buffering.seen_ccs = 0; + + /* Clear future message buffering structure. */ + ssl_buffering_free( ssl ); + /* Cancel timer */ ssl_set_timer( ssl, 0 ); @@ -2686,43 +3150,102 @@ void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* - * Record layer functions + * Handshake layer functions */ /* - * Write current record. - * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg. + * Write (DTLS: or queue) current handshake (including CCS) message. + * + * - fill in handshake headers + * - update handshake checksum + * - DTLS: save message for resending + * - then pass to the record layer + * + * DTLS: except for HelloRequest, messages are only queued, and will only be + * actually sent when calling flight_transmit() or resend(). + * + * Inputs: + * - ssl->out_msglen: 4 + actual handshake message len + * (4 is the size of handshake headers for TLS) + * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) + * - ssl->out_msg + 4: the handshake message body + * + * Outputs, ie state before passing to flight_append() or write_record(): + * - ssl->out_msglen: the length of the record contents + * (including handshake headers but excluding record headers) + * - ssl->out_msg: the record contents (handshake headers + content) */ -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) { - int ret, done = 0, out_msg_type; - size_t len = ssl->out_msglen; + int ret; + const size_t hs_len = ssl->out_msglen - 4; + const unsigned char hs_type = ssl->out_msg[0]; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); + + /* + * Sanity checks + */ + if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + /* In SSLv3, the client might send a NoCertificate alert. */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) + if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ) +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* Whenever we send anything different from a + * HelloRequest we should be in a handshake - double check. */ + if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) { - ; /* Skip special handshake treatment when resending */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - else #endif + + /* Double-check that we did not exceed the bounds + * of the outgoing record buffer. + * This should never fail as the various message + * writing functions must obey the bounds of the + * outgoing record buffer, but better be safe. + * + * Note: We deliberately do not check for the MTU or MFL here. + */ + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " + "size %u, maximum %u", + (unsigned) ssl->out_msglen, + (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Fill handshake headers + */ if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) { - out_msg_type = ssl->out_msg[0]; - - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST && - ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); - ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); - ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); + ssl->out_msg[1] = (unsigned char)( hs_len >> 16 ); + ssl->out_msg[2] = (unsigned char)( hs_len >> 8 ); + ssl->out_msg[3] = (unsigned char)( hs_len ); /* * DTLS has additional fields in the Handshake layer, @@ -2735,12 +3258,20 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { /* Make room for the additional DTLS fields */ - memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); + if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " + "size %u, maximum %u", + (unsigned) ( hs_len ), + (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); ssl->out_msglen += 8; - len += 8; /* Write message_seq and update it, except for HelloRequest */ - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) { ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; @@ -2752,23 +3283,23 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) ssl->out_msg[5] = 0; } - /* We don't fragment, so frag_offset = 0 and frag_len = len */ + /* Handshake hashes are computed without fragmentation, + * so set frag_offset = 0 and frag_len = hs_len for now */ memset( ssl->out_msg + 6, 0x00, 3 ); memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); } #endif /* MBEDTLS_SSL_PROTO_DTLS */ - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) - ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); + /* Update running hashes of handshake messages seen */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); } - /* Save handshake and CCS messages for resending */ + /* Either send now, or just save to be sent (and resent) later */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING && - ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || - ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) + ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) { if( ( ret = ssl_flight_append( ssl ) ) != 0 ) { @@ -2776,7 +3307,40 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) return( ret ); } } + else #endif + { + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ + +/* + * Write current record. + * + * Uses: + * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) + * - ssl->out_msglen: length of the record content (excl headers) + * - ssl->out_msg: record content + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + uint8_t flush = force_flush; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->transform_out != NULL && @@ -2810,10 +3374,14 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ if( !done ) { + unsigned i; + size_t protected_record_size; + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, ssl->conf->transport, ssl->out_hdr + 1 ); + memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); ssl->out_len[0] = (unsigned char)( len >> 8 ); ssl->out_len[1] = (unsigned char)( len ); @@ -2830,18 +3398,76 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) ssl->out_len[1] = (unsigned char)( len ); } - ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; + protected_record_size = len + mbedtls_ssl_hdr_len( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* In case of DTLS, double-check that we don't exceed + * the remaining space in the datagram. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + + if( protected_record_size > (size_t) ret ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], - ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); + "version = [%d:%d], msglen = %d", + ssl->out_hdr[0], ssl->out_hdr[1], + ssl->out_hdr[2], len ) ); MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", - ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); + ssl->out_hdr, protected_record_size ); + + ssl->out_left += protected_record_size; + ssl->out_hdr += protected_record_size; + ssl_update_out_pointers( ssl, ssl->transform_out ); + + for( i = 8; i > ssl_ep_len( ssl ); i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } } - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + flush == SSL_DONT_FORCE_FLUSH ) + { + size_t remaining; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", + ret ); + return( ret ); + } + + remaining = (size_t) ret; + if( remaining == 0 ) + { + flush = SSL_FORCE_FLUSH; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( flush == SSL_FORCE_FLUSH ) && + ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); return( ret ); @@ -2853,6 +3479,52 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL_PROTO_DTLS) + +static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) + { + return( 1 ); + } + return( 0 ); +} + +static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11] ); +} + +static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8] ); +} + +static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) +{ + uint32_t msg_len, frag_off, frag_len; + + msg_len = ssl_get_hs_total_len( ssl ); + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + if( frag_off > msg_len ) + return( -1 ); + + if( frag_len > msg_len - frag_off ) + return( -1 ); + + if( frag_len + 12 > ssl->in_msglen ) + return( -1 ); + + return( 0 ); +} + /* * Mark bits in bitmask (used for DTLS HS reassembly) */ @@ -2914,162 +3586,30 @@ static int ssl_bitmask_check( unsigned char *mask, size_t len ) return( 0 ); } -/* - * Reassemble fragmented DTLS handshake messages. - * - * Use a temporary buffer for reassembly, divided in two parts: - * - the first holds the reassembled message (including handshake header), - * - the second holds a bitmask indicating which parts of the message - * (excluding headers) have been received so far. - */ -static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) +/* msg_len does not include the handshake header */ +static size_t ssl_get_reassembly_buffer_size( size_t msg_len, + unsigned add_bitmap ) { - unsigned char *msg, *bitmask; - size_t frag_len, frag_off; - size_t msg_len = ssl->in_hslen - 12; /* Without headers */ + size_t alloc_len; - if( ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } + alloc_len = 12; /* Handshake header */ + alloc_len += msg_len; /* Content buffer */ - /* - * For first fragment, check size and allocate buffer - */ - if( ssl->handshake->hs_msg == NULL ) - { - size_t alloc_len; + if( add_bitmap ) + alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", - msg_len ) ); - - if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* The bitmask needs one bit per byte of message excluding header */ - alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); - - ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); - if( ssl->handshake->hs_msg == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Prepare final header: copy msg_type, length and message_seq, - * then add standardised fragment_offset and fragment_length */ - memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); - memset( ssl->handshake->hs_msg + 6, 0, 3 ); - memcpy( ssl->handshake->hs_msg + 9, - ssl->handshake->hs_msg + 1, 3 ); - } - else - { - /* Make sure msg_type and length are consistent */ - if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - - msg = ssl->handshake->hs_msg + 12; - bitmask = msg + msg_len; - - /* - * Check and copy current fragment - */ - frag_off = ( ssl->in_msg[6] << 16 ) | - ( ssl->in_msg[7] << 8 ) | - ssl->in_msg[8]; - frag_len = ( ssl->in_msg[9] << 16 ) | - ( ssl->in_msg[10] << 8 ) | - ssl->in_msg[11]; - - if( frag_off + frag_len > msg_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", - frag_off, frag_len, msg_len ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( frag_len + 12 > ssl->in_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", - frag_len, ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", - frag_off, frag_len ) ); - - memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); - ssl_bitmask_set( bitmask, frag_off, frag_len ); - - /* - * Do we have the complete message by now? - * If yes, finalize it, else ask to read the next record. - */ - if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); - - if( frag_len + 12 < ssl->in_msglen ) - { - /* - * We'got more handshake messages in the same record. - * This case is not handled now because no know implementation does - * that and it's hard to test, so we prefer to fail cleanly for now. - */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - if( ssl->in_left > ssl->next_record_offset ) - { - /* - * We've got more data in the buffer after the current record, - * that we don't want to overwrite. Move it before writing the - * reassembled message, and adjust in_left and next_record_offset. - */ - unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; - unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; - size_t remain_len = ssl->in_left - ssl->next_record_offset; - - /* First compute and check new lengths */ - ssl->next_record_offset = new_remain - ssl->in_hdr; - ssl->in_left = ssl->next_record_offset + remain_len; - - if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - - (size_t)( ssl->in_hdr - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - memmove( new_remain, cur_remain, remain_len ); - } - - memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); - - mbedtls_free( ssl->handshake->hs_msg ); - ssl->handshake->hs_msg = NULL; - - MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", - ssl->in_msg, ssl->in_hslen ); - - return( 0 ); + return( alloc_len ); } + #endif /* MBEDTLS_SSL_PROTO_DTLS */ +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); +} + int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) { if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) @@ -3079,10 +3619,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } - ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ( - ( ssl->in_msg[1] << 16 ) | - ( ssl->in_msg[2] << 8 ) | - ssl->in_msg[3] ); + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" " %d, type = %d, hslen = %d", @@ -3094,10 +3631,26 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) int ret; unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - /* ssl->handshake is NULL when receiving ClientHello for renego */ - if( ssl->handshake != NULL && - recv_msg_seq != ssl->handshake->in_msg_seq ) + if( ssl_check_hs_header( ssl ) != 0 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->handshake != NULL && + ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + recv_msg_seq != ssl->handshake->in_msg_seq ) || + ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) + { + if( recv_msg_seq > ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + /* Retransmit only on last message from previous flight, to avoid * too many retransmissions. * Besides, No sane server ever retransmits HelloVerifyRequest */ @@ -3123,24 +3676,18 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) ssl->handshake->in_msg_seq ) ); } - return( MBEDTLS_ERR_SSL_WANT_READ ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); } /* Wait until message completion to increment in_msg_seq */ - /* Reassemble if current message is fragmented or reassembly is - * already in progress */ - if( ssl->in_msglen < ssl->in_hslen || - memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || - memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 || - ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) + /* Message reassembly is handled alongside buffering of future + * messages; the commonality is that both handshake fragments and + * future messages cannot be forwarded immediately to the + * handshake logic layer. */ + if( ssl_hs_is_proper_fragment( ssl ) == 1 ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); - - if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); - return( ret ); - } + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); } } else @@ -3157,9 +3704,9 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) { + mbedtls_ssl_handshake_params * const hs = ssl->handshake; - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && - ssl->handshake != NULL ) + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) { ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); } @@ -3169,7 +3716,29 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL ) { - ssl->handshake->in_msg_seq++; + unsigned offset; + mbedtls_ssl_hs_buffer *hs_buf; + + /* Increment handshake sequence number */ + hs->in_msg_seq++; + + /* + * Clear up handshake buffering and reassembly structure. + */ + + /* Free first entry */ + ssl_buffering_free_slot( ssl, 0 ); + + /* Shift all other entries */ + for( offset = 0, hs_buf = &hs->buffering.hs[0]; + offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; + offset++, hs_buf++ ) + { + *hs_buf = *(hs_buf + 1); + } + + /* Create a fresh last entry */ + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); } #endif } @@ -3422,13 +3991,13 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) ssl->conf->p_cookie, ssl->cli_id, ssl->cli_id_len, ssl->in_buf, ssl->in_left, - ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); + ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) { - /* Dont check write errors as we can't do anything here. + /* Don't check write errors as we can't do anything here. * If the error is permanent we'll catch it later, * if it's not, then hopefully it'll work next time. */ (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); @@ -3473,7 +4042,6 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) */ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) { - int ret; int major_ver, minor_ver; MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); @@ -3495,12 +4063,13 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 ) - { - return( ret ); - } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* Silently ignore invalid DTLS records as recommended by RFC 6347 + * Section 4.1.2.7 */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } @@ -3519,88 +4088,30 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) } /* Check length against the size of our buffer */ - if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN + if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_msg - ssl->in_buf ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } - /* Check length against bounds of the current transform and version */ - if( ssl->transform_in == NULL ) - { - if( ssl->in_msglen < 1 || - ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - else - { - if( ssl->in_msglen < ssl->transform_in->minlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * TLS encrypted messages can have up to 256 bytes of padding - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && - ssl->in_msglen > ssl->transform_in->minlen + - MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif - } - /* - * DTLS-related tests done last, because most of them may result in - * silently dropping the record (but not the whole datagram), and we only - * want to consider that after ensuring that the "basic" fields (type, - * version, length) are sane. + * DTLS-related tests. + * Check epoch before checking length constraint because + * the latter varies with the epoch. E.g., if a ChangeCipherSpec + * message gets duplicated before the corresponding Finished message, + * the second ChangeCipherSpec should be discarded because it belongs + * to an old epoch, but not because its length is shorter than + * the minimum record length for packets using the new record transform. + * Note that these two kinds of failures are handled differently, + * as an unexpected record is silently skipped but an invalid + * record leads to the entire datagram being dropped. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; - /* Drop unexpected ChangeCipherSpec messages */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - - /* Drop unexpected ApplicationData records, - * except at the beginning of renegotiations */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && - ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->state == MBEDTLS_SSL_SERVER_HELLO ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - /* Check epoch (and sequence number) with DTLS */ if( rec_epoch != ssl->in_epoch ) { @@ -3628,7 +4139,16 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + /* Consider buffering the record. */ + if( rec_epoch == (unsigned int) ssl->in_epoch + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) @@ -3640,9 +4160,65 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); } #endif + + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Check length against bounds of the current transform and version */ + if( ssl->transform_in == NULL ) + { + if( ssl->in_msglen < 1 || + ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + else + { + if( ssl->in_msglen < ssl->transform_in->minlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * TLS encrypted messages can have up to 256 bytes of padding + */ + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && + ssl->in_msglen > ssl->transform_in->minlen + + MBEDTLS_SSL_IN_CONTENT_LEN + 256 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif + } + return( 0 ); } @@ -3683,7 +4259,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", ssl->in_msg, ssl->in_msglen ); - if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); @@ -3721,33 +4297,89 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); * RFC 6347 4.1.2.7) and continue reading until a valid record is found. * */ -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) + +/* Helper functions for mbedtls_ssl_read_record(). */ +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); +static int ssl_get_next_record( mbedtls_ssl_context *ssl ); +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ) { int ret; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); - do { + if( ssl->keep_current_message == 0 ) + { + do { - if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) + ret = ssl_consume_current_message( ssl ); + if( ret != 0 ) + return( ret ); + + if( ssl_record_is_in_progress( ssl ) == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + int have_buffered = 0; + + /* We only check for buffered messages if the + * current datagram is fully consumed. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl_next_record_is_in_datagram( ssl ) == 0 ) + { + if( ssl_load_buffered_message( ssl ) == 0 ) + have_buffered = 1; + } + + if( have_buffered == 0 ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ret = ssl_get_next_record( ssl ); + if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) + continue; + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); + return( ret ); + } + } + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + /* Buffer future message */ + ret = ssl_buffer_message( ssl ); + if( ret != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || + MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); + + if( 0 != ret ) { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); return( ret ); } - ret = mbedtls_ssl_handle_message_type( ssl ); - - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); - - if( 0 != ret ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); - return( ret ); + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + update_hs_digest == 1 ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + else { - mbedtls_ssl_update_handshake_status( ssl ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); + ssl->keep_current_message = 0; } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); @@ -3755,34 +4387,586 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) return( 0 ); } -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) { - int ret; + if( ssl->in_left > ssl->next_record_offset ) + return( 1 ); - if( ssl->in_hslen != 0 && ssl->in_hslen < ssl->in_msglen ) + return( 0 ); +} + +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * hs_buf; + int ret = 0; + + if( hs == NULL ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); + + if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || + ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) { - /* - * Get next Handshake message in the current record - */ - ssl->in_msglen -= ssl->in_hslen; + /* Check if we have seen a ChangeCipherSpec before. + * If yes, synthesize a CCS record. */ + if( !hs->buffering.seen_ccs ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); + ret = -1; + goto exit; + } - memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, - ssl->in_msglen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); + ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->in_msglen = 1; + ssl->in_msg[0] = 1; - MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", - ssl->in_msg, ssl->in_msglen ); + /* As long as they are equal, the exact value doesn't matter. */ + ssl->in_left = 0; + ssl->next_record_offset = 0; + hs->buffering.seen_ccs = 0; + goto exit; + } + +#if defined(MBEDTLS_DEBUG_C) + /* Debug only */ + { + unsigned offset; + for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + { + hs_buf = &hs->buffering.hs[offset]; + if( hs_buf->is_valid == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", + hs->in_msg_seq + offset, + hs_buf->is_complete ? "fully" : "partially" ) ); + } + } + } +#endif /* MBEDTLS_DEBUG_C */ + + /* Check if we have buffered and/or fully reassembled the + * next handshake message. */ + hs_buf = &hs->buffering.hs[0]; + if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) + { + /* Synthesize a record containing the buffered HS message. */ + size_t msg_len = ( hs_buf->data[1] << 16 ) | + ( hs_buf->data[2] << 8 ) | + hs_buf->data[3]; + + /* Double-check that we haven't accidentally buffered + * a message that doesn't fit into the input buffer. */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", + hs_buf->data, msg_len + 12 ); + + ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->in_hslen = msg_len + 12; + ssl->in_msglen = msg_len + 12; + memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); + + ret = 0; + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", + hs->in_msg_seq ) ); + } + + ret = -1; + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); + return( ret ); +} + +static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, + size_t desired ) +{ + int offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", + (unsigned) desired ) ); + + /* Get rid of future records epoch first, if such exist. */ + ssl_free_buffered_record( ssl ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); return( 0 ); } - ssl->in_hslen = 0; + /* We don't have enough space to buffer the next expected handshake + * message. Remove buffers used for future messages to gain space, + * starting with the most distant one. */ + for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; + offset >= 0; offset-- ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", + offset ) ); + ssl_buffering_free_slot( ssl, (uint8_t) offset ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); + return( 0 ); + } + } + + return( -1 ); +} + +static int ssl_buffer_message( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); + + switch( ssl->in_msgtype ) + { + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); + + hs->buffering.seen_ccs = 1; + break; + + case MBEDTLS_SSL_MSG_HANDSHAKE: + { + unsigned recv_msg_seq_offset; + unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + mbedtls_ssl_hs_buffer *hs_buf; + size_t msg_len = ssl->in_hslen - 12; + + /* We should never receive an old handshake + * message - double-check nonetheless. */ + if( recv_msg_seq < ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; + if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + { + /* Silently ignore -- message too far in the future */ + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "Ignore future HS message with sequence number %u, " + "buffering window %u - %u", + recv_msg_seq, ssl->handshake->in_msg_seq, + ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); + + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", + recv_msg_seq, recv_msg_seq_offset ) ); + + hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; + + /* Check if the buffering for this seq nr has already commenced. */ + if( !hs_buf->is_valid ) + { + size_t reassembly_buf_sz; + + hs_buf->is_fragmented = + ( ssl_hs_is_proper_fragment( ssl ) == 1 ); + + /* We copy the message back into the input buffer + * after reassembly, so check that it's not too large. + * This is an implementation-specific limitation + * and not one from the standard, hence it is not + * checked in ssl_check_hs_header(). */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + /* Ignore message */ + goto exit; + } + + /* Check if we have enough space to buffer the message. */ + if( hs->buffering.total_bytes_buffered > + MBEDTLS_SSL_DTLS_MAX_BUFFERING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, + hs_buf->is_fragmented ); + + if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + if( recv_msg_seq_offset > 0 ) + { + /* If we can't buffer a future message because + * of space limitations -- ignore. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n", + (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + } + + if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n", + (unsigned) msg_len, + (unsigned) reassembly_buf_sz, + MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", + msg_len ) ); + + hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); + if( hs_buf->data == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + hs_buf->data_len = reassembly_buf_sz; + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( hs_buf->data, ssl->in_msg, 6 ); + memset( hs_buf->data + 6, 0, 3 ); + memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); + + hs_buf->is_valid = 1; + + hs->buffering.total_bytes_buffered += reassembly_buf_sz; + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); + /* Ignore */ + goto exit; + } + } + + if( !hs_buf->is_complete ) + { + size_t frag_len, frag_off; + unsigned char * const msg = hs_buf->data + 12; + + /* + * Check and copy current fragment + */ + + /* Validation of header fields already done in + * mbedtls_ssl_prepare_handshake_record(). */ + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", + frag_off, frag_len ) ); + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + + if( hs_buf->is_fragmented ) + { + unsigned char * const bitmask = msg + msg_len; + ssl_bitmask_set( bitmask, frag_off, frag_len ); + hs_buf->is_complete = ( ssl_bitmask_check( bitmask, + msg_len ) == 0 ); + } + else + { + hs_buf->is_complete = 1; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", + hs_buf->is_complete ? "" : "not yet " ) ); + } + + break; + } + + default: + /* We don't buffer other types of messages. */ + break; + } + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) +{ /* - * Read the record header and parse it + * Consume last content-layer message and potentially + * update in_msglen which keeps track of the contents' + * consumption state. + * + * (1) Handshake messages: + * Remove last handshake message, move content + * and adapt in_msglen. + * + * (2) Alert messages: + * Consume whole record content, in_msglen = 0. + * + * (3) Change cipher spec: + * Consume whole record content, in_msglen = 0. + * + * (4) Application data: + * Don't do anything - the record layer provides + * the application data as a stream transport + * and consumes through mbedtls_ssl_read only. + * */ + + /* Case (1): Handshake messages */ + if( ssl->in_hslen != 0 ) + { + /* Hard assertion to be sure that no application data + * is in flight, as corrupting ssl->in_msglen during + * ssl->in_offt != NULL is fatal. */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Get next Handshake message in the current record + */ + + /* Notes: + * (1) in_hslen is not necessarily the size of the + * current handshake content: If DTLS handshake + * fragmentation is used, that's the fragment + * size instead. Using the total handshake message + * size here is faulty and should be changed at + * some point. + * (2) While it doesn't seem to cause problems, one + * has to be very careful not to assume that in_hslen + * is always <= in_msglen in a sensible communication. + * Again, it's wrong for DTLS handshake fragmentation. + * The following check is therefore mandatory, and + * should not be treated as a silently corrected assertion. + * Additionally, ssl->in_hslen might be arbitrarily out of + * bounds after handling a DTLS message with an unexpected + * sequence number, see mbedtls_ssl_prepare_handshake_record. + */ + if( ssl->in_hslen < ssl->in_msglen ) + { + ssl->in_msglen -= ssl->in_hslen; + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + } + else + { + ssl->in_msglen = 0; + } + + ssl->in_hslen = 0; + } + /* Case (4): Application data */ + else if( ssl->in_offt != NULL ) + { + return( 0 ); + } + /* Everything else (CCS & Alerts) */ + else + { + ssl->in_msglen = 0; + } + + return( 0 ); +} + +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen > 0 ) + return( 1 ); + + return( 0 ); +} + #if defined(MBEDTLS_SSL_PROTO_DTLS) -read_record_header: -#endif + +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + if( hs == NULL ) + return; + + if( hs->buffering.future_record.data != NULL ) + { + hs->buffering.total_bytes_buffered -= + hs->buffering.future_record.len; + + mbedtls_free( hs->buffering.future_record.data ); + hs->buffering.future_record.data = NULL; + } +} + +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + unsigned char * rec; + size_t rec_len; + unsigned rec_epoch; + + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 0 ); + + if( hs == NULL ) + return( 0 ); + + rec = hs->buffering.future_record.data; + rec_len = hs->buffering.future_record.len; + rec_epoch = hs->buffering.future_record.epoch; + + if( rec == NULL ) + return( 0 ); + + /* Only consider loading future records if the + * input buffer is empty. */ + if( ssl_next_record_is_in_datagram( ssl ) == 1 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); + + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); + + /* Double-check that the record is not too large */ + if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN - + (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->in_hdr, rec, rec_len ); + ssl->in_left = rec_len; + ssl->next_record_offset = 0; + + ssl_free_buffered_record( ssl ); + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); + return( 0 ); +} + +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + size_t const rec_hdr_len = 13; + size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen; + + /* Don't buffer future records outside handshakes. */ + if( hs == NULL ) + return( 0 ); + + /* Only buffer handshake records (we are only interested + * in Finished messages). */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + return( 0 ); + + /* Don't buffer more than one future epoch record. */ + if( hs->buffering.future_record.data != NULL ) + return( 0 ); + + /* Don't buffer record if there's not enough buffering space remaining. */ + if( total_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n", + (unsigned) total_buf_sz, MBEDTLS_SSL_DTLS_MAX_BUFFERING, + (unsigned) hs->buffering.total_bytes_buffered ) ); + return( 0 ); + } + + /* Buffer record */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", + ssl->in_epoch + 1 ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", ssl->in_hdr, + rec_hdr_len + ssl->in_msglen ); + + /* ssl_parse_record_header() only considers records + * of the next epoch as candidates for buffering. */ + hs->buffering.future_record.epoch = ssl->in_epoch + 1; + hs->buffering.future_record.len = total_buf_sz; + + hs->buffering.future_record.data = + mbedtls_calloc( 1, hs->buffering.future_record.len ); + if( hs->buffering.future_record.data == NULL ) + { + /* If we run out of RAM trying to buffer a + * record from the next epoch, just ignore. */ + return( 0 ); + } + + memcpy( hs->buffering.future_record.data, ssl->in_hdr, total_buf_sz ); + + hs->buffering.total_bytes_buffered += total_buf_sz; + return( 0 ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_get_next_record( mbedtls_ssl_context *ssl ) +{ + int ret; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* We might have buffered a future record; if so, + * and if the epoch matches now, load it. + * On success, this call will set ssl->in_left to + * the length of the buffered record, so that + * the calls to ssl_fetch_input() below will + * essentially be no-ops. */ + ret = ssl_load_buffered_record( ssl ); + if( ret != 0 ) + return( ret ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) { @@ -3796,6 +4980,16 @@ read_record_header: if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) { + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = ssl_buffer_future_record( ssl ); + if( ret != 0 ) + return( ret ); + + /* Fall through to handling of unexpected records */ + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) { /* Skip unexpected record (but not whole datagram) */ @@ -3816,7 +5010,7 @@ read_record_header: } /* Get next record */ - goto read_record_header; + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); } #endif return( ret ); @@ -3835,7 +5029,13 @@ read_record_header: /* Done reading this record, get ready for the next one */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); + if( ssl->next_record_offset < ssl->in_left ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); + } + } else #endif ssl->in_left = 0; @@ -3875,8 +5075,14 @@ read_record_header: } #endif + /* As above, invalid records cause + * dismissal of the whole datagram. */ + + ssl->next_record_offset = 0; + ssl->in_left = 0; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); - goto read_record_header; + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); } return( ret ); @@ -3897,46 +5103,6 @@ read_record_header: } } - /* - * When we sent the last flight of the handshake, we MUST respond to a - * retransmit of the peer's previous flight with a retransmit. (In - * practice, only the Finished message will make it, other messages - * including CCS use the old transform so they're dropped as invalid.) - * - * If the record we received is not a handshake message, however, it - * means the peer received our last flight so we can clean up - * handshake info. - * - * This check needs to be done before prepare_handshake() due to an edge - * case: if the client immediately requests renegotiation, this - * finishes the current handshake first, avoiding the new ClientHello - * being mistaken for an ancient message in the current handshake. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) ); - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - else - { - ssl_handshake_wrapup_free_hs_transform( ssl ); - } - } -#endif - return( 0 ); } @@ -3955,8 +5121,51 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) } } + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( ssl->in_msglen != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", + ssl->in_msg[0] ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } +#endif + } + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", ssl->in_msg[0], ssl->in_msg[1] ) ); @@ -3981,7 +5190,7 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) ); /* Will be handled when trying to parse ServerHello */ return( 0 ); } @@ -4003,6 +5212,15 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) return MBEDTLS_ERR_SSL_NON_FATAL; } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ssl_handshake_wrapup_free_hs_transform( ssl ); + } +#endif + return( 0 ); } @@ -4030,18 +5248,18 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; ssl->out_msglen = 2; ssl->out_msg[0] = level; ssl->out_msg[1] = message; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); return( 0 ); @@ -4057,6 +5275,7 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +/* No certificate support -> dummy functions */ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; @@ -4096,7 +5315,10 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } + #else +/* Some certificate support -> implement write and parse */ + int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -4173,10 +5395,10 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) while( crt != NULL ) { n = crt->raw.len; - if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i ) + if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", - i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) ); + i + 3 + n, MBEDTLS_SSL_OUT_CONTENT_LEN ) ); return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); } @@ -4202,9 +5424,9 @@ write_msg: ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -4213,12 +5435,222 @@ write_msg: return( ret ); } +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t i, n; + uint8_t alert; + +#if defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + + /* The client was asked for a certificate but didn't send + one. The client should know what's going on, so we + don't send an alert. */ + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_SRV_C */ + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || + ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + + if( ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* In case we tried to reuse a session but it failed */ + if( ssl->session_negotiate->peer_cert != NULL ) + { + mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); + mbedtls_free( ssl->session_negotiate->peer_cert ); + } + + if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, + sizeof( mbedtls_x509_crt ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + sizeof( mbedtls_x509_crt ) ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); + + i += 3; + + while( i < ssl->in_hslen ) + { + if ( i + 3 > ssl->in_hslen ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + if( ssl->in_msg[i] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, + ssl->in_msg + i, n ); + switch( ret ) + { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + crt_parse_der_failed: + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); + + /* + * On client, make sure the server cert doesn't change during renego to + * avoid "triple handshake" attack: https://secure-resumption.com/ + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->session->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + if( ssl->session->peer_cert->raw.len != + ssl->session_negotiate->peer_cert->raw.len || + memcmp( ssl->session->peer_cert->raw.p, + ssl->session_negotiate->peer_cert->raw.p, + ssl->session->peer_cert->raw.len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} + int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, n; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - int authmode = ssl->conf->authmode; + int ret; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif + void *rs_ctx = NULL; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); @@ -4241,178 +5673,55 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) return( 0 ); } -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) - authmode = ssl->handshake->sni_authmode; -#endif - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && authmode == MBEDTLS_SSL_VERIFY_NONE ) { ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; return( 0 ); } #endif - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) { + goto crt_verify; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); } - ssl->state++; - + if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 ) + { #if defined(MBEDTLS_SSL_SRV_C) -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* - * Check if the client sent an empty certificate - */ - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( ssl->in_msglen == 2 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && - ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE && + authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); - - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + ret = 0; } - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && - ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && - memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); - - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); - } - } -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ -#endif /* MBEDTLS_SSL_SRV_C */ - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + ssl->state++; + return( ret ); } - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || - ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled) + ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; - i = mbedtls_ssl_hs_hdr_len( ssl ); - - /* - * Same message structure as in mbedtls_ssl_write_certificate() - */ - n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; - - if( ssl->in_msg[i] != 0 || - ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - /* In case we tried to reuse a session but it failed */ - if( ssl->session_negotiate->peer_cert != NULL ) - { - mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); - mbedtls_free( ssl->session_negotiate->peer_cert ); - } - - if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, - sizeof( mbedtls_x509_crt ) ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - sizeof( mbedtls_x509_crt ) ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); - - i += 3; - - while( i < ssl->in_hslen ) - { - if( ssl->in_msg[i] != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) - | (unsigned int) ssl->in_msg[i + 2]; - i += 3; - - if( n < 128 || i + n > ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, - ssl->in_msg + i, n ); - if( 0 != ret && ( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND ) != ret ) - { - MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); - return( ret ); - } - - i += n; - } - - MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); - - /* - * On client, make sure the server cert doesn't change during renego to - * avoid "triple handshake" attack: https://secure-resumption.com/ - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - if( ssl->session->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - if( ssl->session->peer_cert->raw.len != - ssl->session_negotiate->peer_cert->raw.len || - memcmp( ssl->session->peer_cert->raw.p, - ssl->session_negotiate->peer_cert->raw.p, - ssl->session->peer_cert->raw.len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - } -#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ +crt_verify: + if( ssl->handshake->ecrs_enabled) + rs_ctx = &ssl->handshake->ecrs_ctx; +#endif if( authmode != MBEDTLS_SSL_VERIFY_NONE ) { @@ -4432,28 +5741,27 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ca_crl = ssl->conf->ca_crl; } - if( ca_chain == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); - return( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED ); - } - /* * Main check: verify certificate */ - ret = mbedtls_x509_crt_verify_with_profile( + ret = mbedtls_x509_crt_verify_restartable( ssl->session_negotiate->peer_cert, ca_chain, ca_crl, ssl->conf->cert_profile, ssl->hostname, &ssl->session_negotiate->verify_result, - ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); +#endif + /* * Secondary checks: always done, but change 'ret' only if it was 0 */ @@ -4466,6 +5774,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) { + ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); if( ret == 0 ) ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; @@ -4474,8 +5784,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_ECP_C */ if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, - ciphersuite_info, - ! ssl->conf->endpoint, + ciphersuite_info, + ! ssl->conf->endpoint, &ssl->session_negotiate->verify_result ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); @@ -4483,10 +5793,73 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; } - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * ssl_parse_certificate even if verification was optional. */ + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) + { ret = 0; + } + + if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if( ret != 0 ) + { + uint8_t alert; + + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) + alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) + alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; + else + alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert ); + } + +#if defined(MBEDTLS_DEBUG_C) + if( ssl->session_negotiate->verify_result != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x", + ssl->session_negotiate->verify_result ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); + } +#endif /* MBEDTLS_DEBUG_C */ } + ssl->state++; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); return( ret ); @@ -4511,9 +5884,9 @@ int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -4528,7 +5901,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -4537,14 +5910,13 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } - if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); - } + /* CCS records are only accepted if they have length 1 and content '1', + * so we don't need to check this here. */ /* * Switch to our negotiated transform and session parameters for inbound @@ -4565,6 +5937,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) if( ++ssl->in_epoch == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); } } @@ -4572,16 +5946,7 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_PROTO_DTLS */ memset( ssl->in_ctr, 0, 8 ); - /* - * Set the in_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->in_msg = ssl->in_iv; + ssl_update_in_pointers( ssl, ssl->transform_negotiate ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_activate != NULL ) @@ -4589,6 +5954,8 @@ int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } } @@ -4634,15 +6001,15 @@ void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) { #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_starts( &ssl->handshake->fin_md5 ); - mbedtls_sha1_starts( &ssl->handshake->fin_sha1 ); + mbedtls_md5_starts_ret( &ssl->handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &ssl->handshake->fin_sha1 ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_starts( &ssl->handshake->fin_sha256, 0 ); + mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 ); #endif #if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_starts( &ssl->handshake->fin_sha512, 1 ); + mbedtls_sha512_starts_ret( &ssl->handshake->fin_sha512, 1 ); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ } @@ -4652,15 +6019,15 @@ static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, { #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_update( &ssl->handshake->fin_md5 , buf, len ); - mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); #endif #if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ } @@ -4670,8 +6037,8 @@ static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - mbedtls_md5_update( &ssl->handshake->fin_md5 , buf, len ); - mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); } #endif @@ -4680,7 +6047,7 @@ static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); } #endif @@ -4688,7 +6055,7 @@ static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); } #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ @@ -4741,38 +6108,38 @@ static void ssl_calc_finished_ssl( memset( padbuf, 0x36, 48 ); - mbedtls_md5_update( &md5, (const unsigned char *) sender, 4 ); - mbedtls_md5_update( &md5, session->master, 48 ); - mbedtls_md5_update( &md5, padbuf, 48 ); - mbedtls_md5_finish( &md5, md5sum ); + mbedtls_md5_update_ret( &md5, (const unsigned char *) sender, 4 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_finish_ret( &md5, md5sum ); - mbedtls_sha1_update( &sha1, (const unsigned char *) sender, 4 ); - mbedtls_sha1_update( &sha1, session->master, 48 ); - mbedtls_sha1_update( &sha1, padbuf, 40 ); - mbedtls_sha1_finish( &sha1, sha1sum ); + mbedtls_sha1_update_ret( &sha1, (const unsigned char *) sender, 4 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf, 40 ); + mbedtls_sha1_finish_ret( &sha1, sha1sum ); memset( padbuf, 0x5C, 48 ); - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, session->master, 48 ); - mbedtls_md5_update( &md5, padbuf, 48 ); - mbedtls_md5_update( &md5, md5sum, 16 ); - mbedtls_md5_finish( &md5, buf ); + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_update_ret( &md5, md5sum, 16 ); + mbedtls_md5_finish_ret( &md5, buf ); - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, session->master, 48 ); - mbedtls_sha1_update( &sha1, padbuf , 40 ); - mbedtls_sha1_update( &sha1, sha1sum, 20 ); - mbedtls_sha1_finish( &sha1, buf + 16 ); + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf , 40 ); + mbedtls_sha1_update_ret( &sha1, sha1sum, 20 ); + mbedtls_sha1_finish_ret( &sha1, buf + 16 ); MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); mbedtls_md5_free( &md5 ); mbedtls_sha1_free( &sha1 ); - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - mbedtls_zeroize( md5sum, sizeof( md5sum ) ); - mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( md5sum, sizeof( md5sum ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } @@ -4820,8 +6187,8 @@ static void ssl_calc_finished_tls( ? "client finished" : "server finished"; - mbedtls_md5_finish( &md5, padbuf ); - mbedtls_sha1_finish( &sha1, padbuf + 16 ); + mbedtls_md5_finish_ret( &md5, padbuf ); + mbedtls_sha1_finish_ret( &sha1, padbuf + 16 ); ssl->handshake->tls_prf( session->master, 48, sender, padbuf, 36, buf, len ); @@ -4831,7 +6198,7 @@ static void ssl_calc_finished_tls( mbedtls_md5_free( &md5 ); mbedtls_sha1_free( &sha1 ); - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } @@ -4872,7 +6239,7 @@ static void ssl_calc_finished_tls_sha256( ? "client finished" : "server finished"; - mbedtls_sha256_finish( &sha256, padbuf ); + mbedtls_sha256_finish_ret( &sha256, padbuf ); ssl->handshake->tls_prf( session->master, 48, sender, padbuf, 32, buf, len ); @@ -4881,7 +6248,7 @@ static void ssl_calc_finished_tls_sha256( mbedtls_sha256_free( &sha256 ); - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } @@ -4921,7 +6288,7 @@ static void ssl_calc_finished_tls_sha384( ? "client finished" : "server finished"; - mbedtls_sha512_finish( &sha512, padbuf ); + mbedtls_sha512_finish_ret( &sha512, padbuf ); ssl->handshake->tls_prf( session->master, 48, sender, padbuf, 48, buf, len ); @@ -4930,7 +6297,7 @@ static void ssl_calc_finished_tls_sha384( mbedtls_sha512_free( &sha512 ); - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); } @@ -4944,7 +6311,7 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) /* * Free our handshake params */ - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); mbedtls_free( ssl->handshake ); ssl->handshake = NULL; @@ -5030,16 +6397,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); - /* - * Set the out_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; + ssl_update_out_pointers( ssl, ssl->transform_negotiate ); ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); @@ -5091,14 +6449,14 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) /* Remember current epoch settings for resending */ ssl->handshake->alt_transform_out = ssl->transform_out; - memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 ); /* Set sequence_number to zero */ - memset( ssl->out_ctr + 2, 0, 6 ); + memset( ssl->cur_out_ctr + 2, 0, 6 ); /* Increment epoch */ for( i = 2; i > 0; i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) break; /* The loop goes to its end iff the counter is wrapping */ @@ -5110,7 +6468,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset( ssl->out_ctr, 0, 8 ); + memset( ssl->cur_out_ctr, 0, 8 ); ssl->transform_out = ssl->transform_negotiate; ssl->session_out = ssl->session_negotiate; @@ -5131,12 +6489,21 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) mbedtls_ssl_send_flight_completed( ssl ); #endif - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); return( 0 ); @@ -5158,7 +6525,7 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); @@ -5167,6 +6534,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -5182,6 +6551,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); } @@ -5189,6 +6560,8 @@ int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) buf, hash_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); } @@ -5229,22 +6602,26 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) defined(MBEDTLS_SSL_PROTO_TLS1_1) mbedtls_md5_init( &handshake->fin_md5 ); mbedtls_sha1_init( &handshake->fin_sha1 ); - mbedtls_md5_starts( &handshake->fin_md5 ); - mbedtls_sha1_starts( &handshake->fin_sha1 ); + mbedtls_md5_starts_ret( &handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &handshake->fin_sha1 ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) mbedtls_sha256_init( &handshake->fin_sha256 ); - mbedtls_sha256_starts( &handshake->fin_sha256, 0 ); + mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 ); #endif #if defined(MBEDTLS_SHA512_C) mbedtls_sha512_init( &handshake->fin_sha512 ); - mbedtls_sha512_starts( &handshake->fin_sha512, 1 ); + mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 ); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ handshake->update_checksum = ssl_update_checksum_start; - handshake->sig_alg = MBEDTLS_SSL_HASH_SHA1; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); +#endif #if defined(MBEDTLS_DHM_C) mbedtls_dhm_init( &handshake->dhm_ctx ); @@ -5260,6 +6637,10 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) #endif #endif +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); +#endif + #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; #endif @@ -5289,7 +6670,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl ) if( ssl->session_negotiate ) mbedtls_ssl_session_free( ssl->session_negotiate ); if( ssl->handshake ) - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); /* * Either the pointers are now NULL or cleared properly and can be freed. @@ -5379,6 +6760,78 @@ static int ssl_cookie_check_dummy( void *ctx, } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ +/* Once ssl->out_hdr as the address of the beginning of the + * next outgoing record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->out_hdr, + * and the caller has to make sure there's space for this. + */ + +static void ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_ctr = ssl->out_hdr + 3; + ssl->out_len = ssl->out_hdr + 11; + ssl->out_iv = ssl->out_hdr + 13; + } + else +#endif + { + ssl->out_ctr = ssl->out_hdr - 8; + ssl->out_len = ssl->out_hdr + 3; + ssl->out_iv = ssl->out_hdr + 5; + } + + /* Adjust out_msg to make space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->out_msg = ssl->out_iv; +} + +/* Once ssl->in_hdr as the address of the beginning of the + * next incoming record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->in_hdr, + * and the caller has to make sure there's space for this. + */ + +static void ssl_update_in_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->in_ctr = ssl->in_hdr + 3; + ssl->in_len = ssl->in_hdr + 11; + ssl->in_iv = ssl->in_hdr + 13; + } + else +#endif + { + ssl->in_ctr = ssl->in_hdr - 8; + ssl->in_len = ssl->in_hdr + 3; + ssl->in_iv = ssl->in_hdr + 5; + } + + /* Offset in_msg from in_iv to allow space for explicit IV, if used. */ + if( transform != NULL && + ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + ssl->in_msg = ssl->in_iv + transform->ivlen - transform->fixed_ivlen; + } + else + ssl->in_msg = ssl->in_iv; +} + /* * Initialize an SSL context */ @@ -5390,61 +6843,87 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) /* * Setup an SSL context */ + +static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) +{ + /* Set the incoming and outgoing record pointers. */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->in_hdr = ssl->in_buf; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ssl->out_hdr = ssl->out_buf + 8; + ssl->in_hdr = ssl->in_buf + 8; + } + + /* Derive other internal pointers. */ + ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); + ssl_update_in_pointers ( ssl, NULL /* no transform enabled */ ); +} + int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf ) { int ret; - const size_t len = MBEDTLS_SSL_BUFFER_LEN; ssl->conf = conf; /* * Prepare base structures */ - if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || - ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) + + /* Set to NULL in case of an error condition */ + ssl->out_buf = NULL; + + ssl->in_buf = mbedtls_calloc( 1, MBEDTLS_SSL_IN_BUFFER_LEN ); + if( ssl->in_buf == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); - mbedtls_free( ssl->in_buf ); - ssl->in_buf = NULL; - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_IN_BUFFER_LEN) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; } -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->out_buf = mbedtls_calloc( 1, MBEDTLS_SSL_OUT_BUFFER_LEN ); + if( ssl->out_buf == NULL ) { - ssl->out_hdr = ssl->out_buf; - ssl->out_ctr = ssl->out_buf + 3; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - - ssl->in_hdr = ssl->in_buf; - ssl->in_ctr = ssl->in_buf + 3; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", MBEDTLS_SSL_OUT_BUFFER_LEN) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; } - else -#endif - { - ssl->out_ctr = ssl->out_buf; - ssl->out_hdr = ssl->out_buf + 8; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - ssl->in_ctr = ssl->in_buf; - ssl->in_hdr = ssl->in_buf + 8; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; - } + ssl_reset_in_out_pointers( ssl ); if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); + goto error; return( 0 ); + +error: + mbedtls_free( ssl->in_buf ); + mbedtls_free( ssl->out_buf ); + + ssl->conf = NULL; + + ssl->in_buf = NULL; + ssl->out_buf = NULL; + + ssl->in_hdr = NULL; + ssl->in_ctr = NULL; + ssl->in_len = NULL; + ssl->in_iv = NULL; + ssl->in_msg = NULL; + + ssl->out_hdr = NULL; + ssl->out_ctr = NULL; + ssl->out_len = NULL; + ssl->out_iv = NULL; + ssl->out_msg = NULL; + + return( ret ); } /* @@ -5458,6 +6937,11 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) { int ret; +#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ + !defined(MBEDTLS_SSL_SRV_C) + ((void) partial); +#endif + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; /* Cancel any possibly running timer */ @@ -5474,12 +6958,10 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; ssl->in_offt = NULL; + ssl_reset_in_out_pointers( ssl ); - ssl->in_msg = ssl->in_buf + 13; ssl->in_msgtype = 0; ssl->in_msglen = 0; - if( partial == 0 ) - ssl->in_left = 0; #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->next_record_offset = 0; ssl->in_epoch = 0; @@ -5490,9 +6972,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->in_hslen = 0; ssl->nb_zero = 0; - ssl->record_read = 0; - ssl->out_msg = ssl->out_buf + 13; + ssl->keep_current_message = 0; + ssl->out_msgtype = 0; ssl->out_msglen = 0; ssl->out_left = 0; @@ -5501,12 +6983,23 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) ssl->split_done = 0; #endif + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); + ssl->transform_in = NULL; ssl->transform_out = NULL; - memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + ssl->session_in = NULL; + ssl->session_out = NULL; + + memset( ssl->out_buf, 0, MBEDTLS_SSL_OUT_BUFFER_LEN ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) if( partial == 0 ) - memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + ssl->in_left = 0; + memset( ssl->in_buf, 0, MBEDTLS_SSL_IN_BUFFER_LEN ); + } #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_reset != NULL ) @@ -5539,7 +7032,9 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) if( partial == 0 ) +#endif { mbedtls_free( ssl->cli_id ); ssl->cli_id = NULL; @@ -5590,7 +7085,15 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) + +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ) +{ + ssl->disable_datagram_packing = !allow_packing; +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, + uint32_t min, uint32_t max ) { conf->hs_timeout_min = min; conf->hs_timeout_max = max; @@ -5640,6 +7143,13 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, ssl->f_recv_timeout = f_recv_timeout; } +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ) +{ + ssl->mtu = mtu; +} +#endif + void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) { conf->read_timeout = timeout; @@ -5726,27 +7236,27 @@ static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, mbedtls_x509_crt *cert, mbedtls_pk_context *key ) { - mbedtls_ssl_key_cert *new; + mbedtls_ssl_key_cert *new_cert; - new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); - if( new == NULL ) + new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new_cert == NULL ) return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - new->cert = cert; - new->key = key; - new->next = NULL; + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; /* Update head is the list was null, else add to the end */ if( *head == NULL ) { - *head = new; + *head = new_cert; } else { mbedtls_ssl_key_cert *cur = *head; while( cur->next != NULL ) cur = cur->next; - cur->next = new; + cur->next = new_cert; } return( 0 ); @@ -5831,17 +7341,24 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, /* Identity len will be encoded on two bytes */ if( ( psk_identity_len >> 16 ) != 0 || - psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - if( conf->psk != NULL || conf->psk_identity != NULL ) + if( conf->psk != NULL ) { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); conf->psk = NULL; + conf->psk_len = 0; + } + if( conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk_identity ); conf->psk_identity = NULL; + conf->psk_identity_len = 0; } if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || @@ -5873,7 +7390,12 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); if( ssl->handshake->psk != NULL ) + { + mbedtls_platform_zeroize( ssl->handshake->psk, + ssl->handshake->psk_len ); mbedtls_free( ssl->handshake->psk ); + ssl->handshake->psk_len = 0; + } if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); @@ -5895,6 +7417,8 @@ void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) { int ret; @@ -5909,6 +7433,24 @@ int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, cons return( 0 ); } +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ) +{ + int ret; + + if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) { @@ -5946,7 +7488,7 @@ void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, { conf->sig_hashes = hashes; } -#endif +#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ #if defined(MBEDTLS_ECP_C) /* @@ -5957,36 +7499,53 @@ void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, { conf->curve_list = curve_list; } -#endif +#endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_X509_CRT_PARSE_C) int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) { - size_t hostname_len; + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; + + /* Check if new hostname is valid before + * making any change to current one */ + if( hostname != NULL ) + { + hostname_len = strlen( hostname ); + + if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ + + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } + + /* Passing NULL as hostname shall clear the old one */ if( hostname == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + { + ssl->hostname = NULL; + } + else + { + ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); + if( ssl->hostname == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - hostname_len = strlen( hostname ); + memcpy( ssl->hostname, hostname, hostname_len ); - if( hostname_len + 1 == 0 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); - - if( ssl->hostname == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( ssl->hostname, hostname, hostname_len ); - - ssl->hostname[hostname_len] = '\0'; + ssl->hostname[hostname_len] = '\0'; + } return( 0 ); } -#endif +#endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, @@ -6006,8 +7565,9 @@ int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **prot const char **p; /* - * "Empty strings MUST NOT be included and byte strings MUST NOT be - * truncated". Check lengths now rather than later. + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. */ tot_len = 0; for( p = protos; *p != NULL; p++ ) @@ -6049,6 +7609,14 @@ void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) } #endif +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) { @@ -6074,7 +7642,7 @@ void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) { if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || - mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN ) + ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -6153,6 +7721,43 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, } #endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *async_config_data ) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_config_data = async_config_data; +} + +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ) +{ + return( conf->p_async_config_data ); +} + +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake == NULL ) + return( NULL ); + else + return( ssl->handshake->user_async_ctx ); +} + +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ) +{ + if( ssl->handshake != NULL ) + ssl->handshake->user_async_ctx = ctx; +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + /* * SSL get accessors */ @@ -6161,6 +7766,61 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); } +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) +{ + /* + * Case A: We're currently holding back + * a message for further processing. + */ + + if( ssl->keep_current_message == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); + return( 1 ); + } + + /* + * Case B: Further records are pending in the current datagram. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->in_left > ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); + return( 1 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Case C: A handshake message is being processed. + */ + + if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); + return( 1 ); + } + + /* + * Case D: An application data message is being processed + */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); + return( 1 ); + } + + /* + * In all other cases, the rest of the message can be dropped. + * As in ssl_get_next_record, this needs to be adapted if + * we implement support for multiple alerts in single records. + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); + return( 0 ); +} + uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) { if( ssl->session != NULL ) @@ -6220,28 +7880,47 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) { - size_t transform_expansion; + size_t transform_expansion = 0; const mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned block_size; + + if( transform == NULL ) + return( (int) mbedtls_ssl_hdr_len( ssl ) ); #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); #endif - if( transform == NULL ) - return( (int) mbedtls_ssl_hdr_len( ssl ) ); - switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) { case MBEDTLS_MODE_GCM: case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_CHACHAPOLY: case MBEDTLS_MODE_STREAM: transform_expansion = transform->minlen; break; case MBEDTLS_MODE_CBC: - transform_expansion = transform->maclen - + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc ); + + block_size = mbedtls_cipher_get_block_size( + &transform->cipher_ctx_enc ); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.1 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + break; default: @@ -6260,21 +7939,91 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) /* * Assume mfl_code is correct since it was checked when set */ - max_len = mfl_code_to_length[ssl->conf->mfl_code]; + max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); - /* - * Check if a smaller max length was negotiated - */ + /* Check if a smaller max length was negotiated */ if( ssl->session_out != NULL && - mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) + ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) { - max_len = mfl_code_to_length[ssl->session_out->mfl_code]; + max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); } - return max_len; + /* During a handshake, use the value being negotiated */ + if( ssl->session_negotiate != NULL && + ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + } + + return( max_len ); } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) +{ + /* Return unlimited mtu for client hello messages to avoid fragmentation. */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO || + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) ) + return ( 0 ); + + if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) + return( ssl->mtu ); + + if( ssl->mtu == 0 ) + return( ssl->handshake->mtu ); + + return( ssl->mtu < ssl->handshake->mtu ? + ssl->mtu : ssl->handshake->mtu ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + (void) ssl; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl_get_current_mtu( ssl ) != 0 ) + { + const size_t mtu = ssl_get_current_mtu( ssl ); + const int ret = mbedtls_ssl_get_record_expansion( ssl ); + const size_t overhead = (size_t) ret; + + if( ret < 0 ) + return( ret ); + + if( mtu <= overhead ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( max_len > mtu - overhead ) + max_len = mtu - overhead; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + + return( (int) max_len ); +} + #if defined(MBEDTLS_X509_CRT_PARSE_C) const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) { @@ -6362,9 +8111,9 @@ static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); return( ret ); } @@ -6481,6 +8230,10 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) */ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) { + size_t ep_len = ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) @@ -6488,8 +8241,12 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) return( 0 ); } - if( memcmp( ssl->in_ctr, ssl->conf->renego_period, 8 ) <= 0 && - memcmp( ssl->out_ctr, ssl->conf->renego_period, 8 ) <= 0 ) + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) { return( 0 ); } @@ -6504,7 +8261,7 @@ static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) */ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) { - int ret, record_read = 0; + int ret; size_t n; if( ssl == NULL || ssl->conf == NULL ) @@ -6521,14 +8278,28 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) if( ssl->handshake != NULL && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) return( ret ); } } #endif + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + #if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + ret = ssl_check_ctr_renegotiate( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); return( ret ); @@ -6538,18 +8309,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) { ret = mbedtls_ssl_handshake( ssl ); - if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) - { - record_read = 1; - } - else if( ret != 0 ) + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); return( ret ); } } - if( ssl->in_offt == NULL ) + /* Loop as long as no application data record is available */ + while( ssl->in_offt == NULL ) { /* Start timer if not already running */ if( ssl->f_get_timer != NULL && @@ -6558,16 +8327,13 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ssl_set_timer( ssl, ssl->conf->read_timeout ); } - if( ! record_read ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) - return( 0 ); + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); } if( ssl->in_msglen == 0 && @@ -6576,7 +8342,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) /* * OpenSSL sends empty messages to randomize the IV */ - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) { if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) return( 0 ); @@ -6586,26 +8352,35 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } } -#if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + #if defined(MBEDTLS_SSL_CLI_C) if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); /* With DTLS, drop the packet (probably from last handshake) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( MBEDTLS_ERR_SSL_WANT_READ ); + { + continue; + } #endif return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) { @@ -6614,27 +8389,58 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) /* With DTLS, drop the packet (probably from last handshake) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( MBEDTLS_ERR_SSL_WANT_READ ); + { + continue; + } #endif return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } -#endif +#endif /* MBEDTLS_SSL_SRV_C */ - if( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || - ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == - MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = ssl_start_renegotiation( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); #if defined(MBEDTLS_SSL_PROTO_SSL3) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { - /* - * SSLv3 does not have a "no_renegotiation" alert - */ - if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); + /* SSLv3 does not have a "no_renegotiation" warning, so + we send a fatal alert and abort the connection. */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } else #endif /* MBEDTLS_SSL_PROTO_SSL3 */ @@ -6657,36 +8463,30 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } } - else - { - /* DTLS clients need to know renego is server-initiated */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; - } -#endif - ret = ssl_start_renegotiation( ssl ); - if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) - { - record_read = 1; - } - else if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); - return( ret ); - } - } - /* If a non-handshake record was read during renego, fallthrough, - * else tell the user they should call mbedtls_ssl_read() again */ - if( ! record_read ) - return( MBEDTLS_ERR_SSL_WANT_READ ); + /* At this point, we don't know whether the renegotiation has been + * completed or not. The cases to consider are the following: + * 1) The renegotiation is complete. In this case, no new record + * has been read yet. + * 2) The renegotiation is incomplete because the client received + * an application data record while awaiting the ServerHello. + * 3) The renegotiation is incomplete because the client received + * a non-handshake, non-application data message while awaiting + * the ServerHello. + * In each of these case, looping will be the proper action: + * - For 1), the next iteration will read a new record and check + * if it's application data. + * - For 2), the loop condition isn't satisfied as application data + * is present, hence continue is the same as break + * - For 3), the loop condition is satisfied and read_record + * will re-deliver the message that was held back by the client + * when expecting the ServerHello. + */ + continue; } +#if defined(MBEDTLS_SSL_RENEGOTIATION) else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) { - if( ssl->conf->renego_max_records >= 0 ) { if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) @@ -6734,7 +8534,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ -#endif +#endif /* MBEDTLS_SSL_PROTO_DTLS */ } n = ( len < ssl->in_msglen ) @@ -6744,11 +8544,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) ssl->in_msglen -= n; if( ssl->in_msglen == 0 ) - /* all bytes consumed */ + { + /* all bytes consumed */ ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } else + { /* more data available */ ssl->in_offt += n; + } MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); @@ -6756,15 +8561,28 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } /* - * Send application data to be encrypted by the SSL layer, - * taking care of max fragment length and buffer size + * Send application data to be encrypted by the SSL layer, taking care of max + * fragment length and buffer size. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. */ static int ssl_write_real( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - int ret; -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); + int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); + const size_t max_len = (size_t) ret; + + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); + return( ret ); + } if( len > max_len ) { @@ -6780,10 +8598,15 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, #endif len = max_len; } -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ if( ssl->out_left != 0 ) { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); @@ -6792,11 +8615,16 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, } else { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ ssl->out_msglen = len; ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; memcpy( ssl->out_msg, buf, len ); - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); @@ -6811,7 +8639,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl, * * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, * then the caller will call us again with the same arguments, so - * remember wether we already did the split or not. + * remember whether we already did the split or not. */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) static int ssl_write_split( mbedtls_ssl_context *ssl, @@ -6931,7 +8759,7 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) mbedtls_md_free( &transform->md_ctx_enc ); mbedtls_md_free( &transform->md_ctx_dec ); - mbedtls_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); + mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); } #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -6948,11 +8776,57 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) } #endif /* MBEDTLS_X509_CRT_PARSE_C */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_buffering_free( mbedtls_ssl_context *ssl ) { + unsigned offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return; + + ssl_free_buffered_record( ssl ); + + for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + ssl_buffering_free_slot( ssl, offset ); +} + +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; + + if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + return; + + if( hs_buf->is_valid == 1 ) + { + hs->buffering.total_bytes_buffered -= hs_buf->data_len; + mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); + mbedtls_free( hs_buf->data ); + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + if( handshake == NULL ) return; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 ) + { + ssl->conf->f_async_cancel( ssl ); + handshake->async_in_progress = 0; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) mbedtls_md5_free( &handshake->fin_md5 ); @@ -6991,7 +8865,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) if( handshake->psk != NULL ) { - mbedtls_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_platform_zeroize( handshake->psk, handshake->psk_len ); mbedtls_free( handshake->psk ); } #endif @@ -7015,13 +8889,18 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - mbedtls_free( handshake->verify_cookie ); - mbedtls_free( handshake->hs_msg ); - ssl_flight_free( handshake->flight ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); #endif - mbedtls_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) ); +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_free( handshake->verify_cookie ); + ssl_flight_free( handshake->flight ); + ssl_buffering_free( ssl ); +#endif + + mbedtls_platform_zeroize( handshake, + sizeof( mbedtls_ssl_handshake_params ) ); } void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) @@ -7041,7 +8920,7 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) mbedtls_free( session->ticket ); #endif - mbedtls_zeroize( session, sizeof( mbedtls_ssl_session ) ); + mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); } /* @@ -7056,20 +8935,20 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) if( ssl->out_buf != NULL ) { - mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->out_buf, MBEDTLS_SSL_OUT_BUFFER_LEN ); mbedtls_free( ssl->out_buf ); } if( ssl->in_buf != NULL ) { - mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->in_buf, MBEDTLS_SSL_IN_BUFFER_LEN ); mbedtls_free( ssl->in_buf ); } #if defined(MBEDTLS_ZLIB_SUPPORT) if( ssl->compress_buf != NULL ) { - mbedtls_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN ); + mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); mbedtls_free( ssl->compress_buf ); } #endif @@ -7082,7 +8961,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) if( ssl->handshake ) { - mbedtls_ssl_handshake_free( ssl->handshake ); + mbedtls_ssl_handshake_free( ssl ); mbedtls_ssl_transform_free( ssl->transform_negotiate ); mbedtls_ssl_session_free( ssl->session_negotiate ); @@ -7100,7 +8979,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_X509_CRT_PARSE_C) if( ssl->hostname != NULL ) { - mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); mbedtls_free( ssl->hostname ); } #endif @@ -7120,7 +8999,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); /* Actually clear after last debug message */ - mbedtls_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); + mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); } /* @@ -7141,7 +9020,7 @@ static int ssl_preset_default_hashes[] = { MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA224, #endif -#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) MBEDTLS_MD_SHA1, #endif MBEDTLS_MD_NONE @@ -7223,6 +9102,10 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; #endif +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; +#endif + #if defined(MBEDTLS_SSL_PROTO_DTLS) conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; @@ -7230,16 +9113,21 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, #if defined(MBEDTLS_SSL_RENEGOTIATION) conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; - memset( conf->renego_period, 0xFF, 7 ); - conf->renego_period[7] = 0x00; + memset( conf->renego_period, 0x00, 2 ); + memset( conf->renego_period + 2, 0xFF, 6 ); #endif #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) if( endpoint == MBEDTLS_SSL_IS_SERVER ) { - if( ( ret = mbedtls_ssl_conf_dh_param( conf, - MBEDTLS_DHM_RFC5114_MODP_2048_P, - MBEDTLS_DHM_RFC5114_MODP_2048_G ) ) != 0 ) + const unsigned char dhm_p[] = + MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; + const unsigned char dhm_g[] = + MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + + if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf, + dhm_p, sizeof( dhm_p ), + dhm_g, sizeof( dhm_g ) ) ) != 0 ) { return( ret ); } @@ -7283,8 +9171,14 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, * Default */ default: - conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_1; /* TLS 1.0 */ + conf->min_major_ver = ( MBEDTLS_SSL_MIN_MAJOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ? + MBEDTLS_SSL_MIN_MAJOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; + conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ? + MBEDTLS_SSL_MIN_MINOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; @@ -7332,11 +9226,17 @@ void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) if( conf->psk != NULL ) { - mbedtls_zeroize( conf->psk, conf->psk_len ); - mbedtls_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); + conf->psk = NULL; conf->psk_len = 0; + } + + if( conf->psk_identity != NULL ) + { + mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; conf->psk_identity_len = 0; } #endif @@ -7345,7 +9245,7 @@ void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) ssl_key_cert_free( conf->key_cert ); #endif - mbedtls_zeroize( conf, sizeof( mbedtls_ssl_config ) ); + mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) ); } #if defined(MBEDTLS_PK_C) && \ @@ -7366,6 +9266,19 @@ unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) return( MBEDTLS_SSL_SIG_ANON ); } +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) +{ + switch( type ) { + case MBEDTLS_PK_RSA: + return( MBEDTLS_SSL_SIG_RSA ); + case MBEDTLS_PK_ECDSA: + case MBEDTLS_PK_ECKEY: + return( MBEDTLS_SSL_SIG_ECDSA ); + default: + return( MBEDTLS_SSL_SIG_ANON ); + } +} + mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) { switch( sig ) @@ -7384,6 +9297,57 @@ mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) } #endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + return( set->rsa ); + case MBEDTLS_PK_ECDSA: + return( set->ecdsa ); + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + if( set->rsa == MBEDTLS_MD_NONE ) + set->rsa = md_alg; + break; + + case MBEDTLS_PK_ECDSA: + if( set->ecdsa == MBEDTLS_MD_NONE ) + set->ecdsa = md_alg; + break; + + default: + break; + } +} + +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ) +{ + set->rsa = md_alg; + set->ecdsa = md_alg; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ + /* * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX */ @@ -7585,7 +9549,7 @@ int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, * and, for DTLS, to/from TLS equivalent. * * For TLS this is the identity. - * For DTLS, use one complement (v -> 255 - v, and then map as follows: + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) */ @@ -7644,8 +9608,7 @@ int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) #if defined(MBEDTLS_MD5_C) case MBEDTLS_SSL_HASH_MD5: - ssl->handshake->calc_verify = ssl_calc_verify_tls; - break; + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_SSL_HASH_SHA1: @@ -7676,4 +9639,149 @@ int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ } +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ) +{ + int ret = 0; + mbedtls_md5_context mbedtls_md5; + mbedtls_sha1_context mbedtls_sha1; + + mbedtls_md5_init( &mbedtls_md5 ); + mbedtls_sha1_init( &mbedtls_sha1 ); + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + if( ( ret = mbedtls_md5_starts_ret( &mbedtls_md5 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_finish_ret( &mbedtls_md5, output ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ret", ret ); + goto exit; + } + + if( ( ret = mbedtls_sha1_starts_ret( &mbedtls_sha1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, data, + data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_finish_ret( &mbedtls_sha1, + output + 16 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ret", ret ); + goto exit; + } + +exit: + mbedtls_md5_free( &mbedtls_md5 ); + mbedtls_sha1_free( &mbedtls_sha1 ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); + +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + int ret = 0; + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + *hashlen = mbedtls_md_get_size( md_info ); + + mbedtls_md_init( &ctx ); + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto exit; + } + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); + goto exit; + } + +exit: + mbedtls_md_free( &ctx ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + #endif /* MBEDTLS_SSL_TLS_C */ diff --git a/Externals/mbedtls/library/threading.c b/Externals/mbedtls/library/threading.c index 83ec01a45f..7c90c7c595 100644 --- a/Externals/mbedtls/library/threading.c +++ b/Externals/mbedtls/library/threading.c @@ -19,6 +19,14 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -29,10 +37,40 @@ #include "mbedtls/threading.h" +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) + +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ + +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define THREADING_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + #if defined(MBEDTLS_THREADING_PTHREAD) static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) { - if( mutex == NULL || mutex->is_valid ) + if( mutex == NULL ) return; mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; @@ -111,8 +149,12 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * mbedtls_mutex_lock = mutex_lock; mbedtls_mutex_unlock = mutex_unlock; +#if defined(MBEDTLS_FS_IO) mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif } /* @@ -120,8 +162,12 @@ void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * */ void mbedtls_threading_free_alt( void ) { +#if defined(MBEDTLS_FS_IO) mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif } #endif /* MBEDTLS_THREADING_ALT */ @@ -131,7 +177,11 @@ void mbedtls_threading_free_alt( void ) #ifndef MUTEX_INIT #define MUTEX_INIT #endif +#if defined(MBEDTLS_FS_IO) mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +#endif +#if defined(THREADING_USE_GMTIME) mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif #endif /* MBEDTLS_THREADING_C */ diff --git a/Externals/mbedtls/library/timing.c b/Externals/mbedtls/library/timing.c index a7c7ff0279..413d133fb6 100644 --- a/Externals/mbedtls/library/timing.c +++ b/Externals/mbedtls/library/timing.c @@ -39,7 +39,8 @@ #if !defined(MBEDTLS_TIMING_ALT) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" #endif @@ -51,6 +52,7 @@ #include #include +#include struct _hr_time { @@ -244,64 +246,72 @@ volatile int mbedtls_timing_alarmed = 0; unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) { - unsigned long delta; - LARGE_INTEGER offset, hfreq; struct _hr_time *t = (struct _hr_time *) val; - QueryPerformanceCounter( &offset ); - QueryPerformanceFrequency( &hfreq ); - - delta = (unsigned long)( ( 1000 * - ( offset.QuadPart - t->start.QuadPart ) ) / - hfreq.QuadPart ); - if( reset ) + { QueryPerformanceCounter( &t->start ); - - return( delta ); + return( 0 ); + } + else + { + unsigned long delta; + LARGE_INTEGER now, hfreq; + QueryPerformanceCounter( &now ); + QueryPerformanceFrequency( &hfreq ); + delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul + / hfreq.QuadPart ); + return( delta ); + } } /* It's OK to use a global because alarm() is supposed to be global anyway */ static DWORD alarmMs; -static DWORD WINAPI TimerProc( LPVOID TimerContext ) +static void TimerProc( void *TimerContext ) { - ((void) TimerContext); + (void) TimerContext; Sleep( alarmMs ); mbedtls_timing_alarmed = 1; - return( TRUE ); + /* _endthread will be called implicitly on return + * That ensures execution of thread funcition's epilogue */ } void mbedtls_set_alarm( int seconds ) { - DWORD ThreadId; + if( seconds == 0 ) + { + /* No need to create a thread for this simple case. + * Also, this shorcut is more reliable at least on MinGW32 */ + mbedtls_timing_alarmed = 1; + return; + } mbedtls_timing_alarmed = 0; alarmMs = seconds * 1000; - CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); + (void) _beginthread( TimerProc, 0, NULL ); } #else /* _WIN32 && !EFIX64 && !EFI32 */ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) { - unsigned long delta; - struct timeval offset; struct _hr_time *t = (struct _hr_time *) val; - gettimeofday( &offset, NULL ); - if( reset ) { - t->start.tv_sec = offset.tv_sec; - t->start.tv_usec = offset.tv_usec; + gettimeofday( &t->start, NULL ); return( 0 ); } - - delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 - + ( offset.tv_usec - t->start.tv_usec ) / 1000; - - return( delta ); + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.tv_usec - t->start.tv_usec ) / 1000; + return( delta ); + } } static void sighandler( int signum ) @@ -315,6 +325,12 @@ void mbedtls_set_alarm( int seconds ) mbedtls_timing_alarmed = 0; signal( SIGALRM, sighandler ); alarm( seconds ); + if( seconds == 0 ) + { + /* alarm(0) cancelled any previous pending alarm, but the + handler won't fire, so raise the flag straight away. */ + mbedtls_timing_alarmed = 1; + } } #endif /* _WIN32 && !EFIX64 && !EFI32 */ @@ -378,13 +394,21 @@ static void busy_msleep( unsigned long msec ) (void) j; } -#define FAIL do \ -{ \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - \ - return( 1 ); \ -} while( 0 ) +#define FAIL do \ + { \ + if( verbose != 0 ) \ + { \ + mbedtls_printf( "failed at line %d\n", __LINE__ ); \ + mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ + cycles, ratio, millisecs, secs, hardfail, \ + (unsigned long) a, (unsigned long) b ); \ + mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ + mbedtls_timing_get_timer( &hires, 0 ), \ + mbedtls_timing_get_timer( &ctx.timer, 0 ), \ + mbedtls_timing_get_delay( &ctx ) ); \ + } \ + return( 1 ); \ + } while( 0 ) /* * Checkup routine @@ -394,22 +418,22 @@ static void busy_msleep( unsigned long msec ) */ int mbedtls_timing_self_test( int verbose ) { - unsigned long cycles, ratio; - unsigned long millisecs, secs; - int hardfail; + unsigned long cycles = 0, ratio = 0; + unsigned long millisecs = 0, secs = 0; + int hardfail = 0; struct mbedtls_timing_hr_time hires; - uint32_t a, b; + uint32_t a = 0, b = 0; mbedtls_timing_delay_context ctx; if( verbose != 0 ) mbedtls_printf( " TIMING tests note: will take some time!\n" ); - if( verbose != 0 ) mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); - for( secs = 1; secs <= 3; secs++ ) { + secs = 1; + (void) mbedtls_timing_get_timer( &hires, 1 ); mbedtls_set_alarm( (int) secs ); @@ -421,12 +445,7 @@ int mbedtls_timing_self_test( int verbose ) /* For some reason on Windows it looks like alarm has an extra delay * (maybe related to creating a new thread). Allow some room here. */ if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } + FAIL; } if( verbose != 0 ) @@ -435,28 +454,22 @@ int mbedtls_timing_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); - for( a = 200; a <= 400; a += 200 ) { - for( b = 200; b <= 400; b += 200 ) - { - mbedtls_timing_set_delay( &ctx, a, a + b ); + a = 800; + b = 400; + mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */ - busy_msleep( a - a / 8 ); - if( mbedtls_timing_get_delay( &ctx ) != 0 ) - FAIL; + busy_msleep( a - a / 4 ); /* T = a - a/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; - busy_msleep( a / 4 ); - if( mbedtls_timing_get_delay( &ctx ) != 1 ) - FAIL; + busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; - busy_msleep( b - a / 8 - b / 8 ); - if( mbedtls_timing_get_delay( &ctx ) != 1 ) - FAIL; - - busy_msleep( b / 4 ); - if( mbedtls_timing_get_delay( &ctx ) != 2 ) - FAIL; - } + busy_msleep( b ); /* T = a + b + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 2 ) + FAIL; } mbedtls_timing_set_delay( &ctx, 0, 0 ); @@ -475,7 +488,6 @@ int mbedtls_timing_self_test( int verbose ) * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; * since the whole test is about 10ms, it shouldn't happen twice in a row. */ - hardfail = 0; hard_test: if( hardfail > 1 ) diff --git a/Externals/mbedtls/library/version.c b/Externals/mbedtls/library/version.c index 6ca80d4695..fd96750885 100644 --- a/Externals/mbedtls/library/version.c +++ b/Externals/mbedtls/library/version.c @@ -30,7 +30,7 @@ #include "mbedtls/version.h" #include -unsigned int mbedtls_version_get_number() +unsigned int mbedtls_version_get_number( void ) { return( MBEDTLS_VERSION_NUMBER ); } diff --git a/Externals/mbedtls/library/version_features.c b/Externals/mbedtls/library/version_features.c index e866e67a23..24143d052c 100644 --- a/Externals/mbedtls/library/version_features.c +++ b/Externals/mbedtls/library/version_features.c @@ -36,6 +36,12 @@ static const char *features[] = { #if defined(MBEDTLS_HAVE_ASM) "MBEDTLS_HAVE_ASM", #endif /* MBEDTLS_HAVE_ASM */ +#if defined(MBEDTLS_NO_UDBL_DIVISION) + "MBEDTLS_NO_UDBL_DIVISION", +#endif /* MBEDTLS_NO_UDBL_DIVISION */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) + "MBEDTLS_NO_64BIT_MULTIPLICATION", +#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ #if defined(MBEDTLS_HAVE_SSE2) "MBEDTLS_HAVE_SSE2", #endif /* MBEDTLS_HAVE_SSE2 */ @@ -69,12 +75,18 @@ static const char *features[] = { #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) "MBEDTLS_PLATFORM_NV_SEED_ALT", #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ #if defined(MBEDTLS_DEPRECATED_WARNING) "MBEDTLS_DEPRECATED_WARNING", #endif /* MBEDTLS_DEPRECATED_WARNING */ #if defined(MBEDTLS_DEPRECATED_REMOVED) "MBEDTLS_DEPRECATED_REMOVED", #endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_CHECK_PARAMS) + "MBEDTLS_CHECK_PARAMS", +#endif /* MBEDTLS_CHECK_PARAMS */ #if defined(MBEDTLS_TIMING_ALT) "MBEDTLS_TIMING_ALT", #endif /* MBEDTLS_TIMING_ALT */ @@ -84,18 +96,42 @@ static const char *features[] = { #if defined(MBEDTLS_ARC4_ALT) "MBEDTLS_ARC4_ALT", #endif /* MBEDTLS_ARC4_ALT */ +#if defined(MBEDTLS_ARIA_ALT) + "MBEDTLS_ARIA_ALT", +#endif /* MBEDTLS_ARIA_ALT */ #if defined(MBEDTLS_BLOWFISH_ALT) "MBEDTLS_BLOWFISH_ALT", #endif /* MBEDTLS_BLOWFISH_ALT */ #if defined(MBEDTLS_CAMELLIA_ALT) "MBEDTLS_CAMELLIA_ALT", #endif /* MBEDTLS_CAMELLIA_ALT */ +#if defined(MBEDTLS_CCM_ALT) + "MBEDTLS_CCM_ALT", +#endif /* MBEDTLS_CCM_ALT */ +#if defined(MBEDTLS_CHACHA20_ALT) + "MBEDTLS_CHACHA20_ALT", +#endif /* MBEDTLS_CHACHA20_ALT */ +#if defined(MBEDTLS_CHACHAPOLY_ALT) + "MBEDTLS_CHACHAPOLY_ALT", +#endif /* MBEDTLS_CHACHAPOLY_ALT */ +#if defined(MBEDTLS_CMAC_ALT) + "MBEDTLS_CMAC_ALT", +#endif /* MBEDTLS_CMAC_ALT */ #if defined(MBEDTLS_DES_ALT) "MBEDTLS_DES_ALT", #endif /* MBEDTLS_DES_ALT */ -#if defined(MBEDTLS_XTEA_ALT) - "MBEDTLS_XTEA_ALT", -#endif /* MBEDTLS_XTEA_ALT */ +#if defined(MBEDTLS_DHM_ALT) + "MBEDTLS_DHM_ALT", +#endif /* MBEDTLS_DHM_ALT */ +#if defined(MBEDTLS_ECJPAKE_ALT) + "MBEDTLS_ECJPAKE_ALT", +#endif /* MBEDTLS_ECJPAKE_ALT */ +#if defined(MBEDTLS_GCM_ALT) + "MBEDTLS_GCM_ALT", +#endif /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_NIST_KW_ALT) + "MBEDTLS_NIST_KW_ALT", +#endif /* MBEDTLS_NIST_KW_ALT */ #if defined(MBEDTLS_MD2_ALT) "MBEDTLS_MD2_ALT", #endif /* MBEDTLS_MD2_ALT */ @@ -105,9 +141,15 @@ static const char *features[] = { #if defined(MBEDTLS_MD5_ALT) "MBEDTLS_MD5_ALT", #endif /* MBEDTLS_MD5_ALT */ +#if defined(MBEDTLS_POLY1305_ALT) + "MBEDTLS_POLY1305_ALT", +#endif /* MBEDTLS_POLY1305_ALT */ #if defined(MBEDTLS_RIPEMD160_ALT) "MBEDTLS_RIPEMD160_ALT", #endif /* MBEDTLS_RIPEMD160_ALT */ +#if defined(MBEDTLS_RSA_ALT) + "MBEDTLS_RSA_ALT", +#endif /* MBEDTLS_RSA_ALT */ #if defined(MBEDTLS_SHA1_ALT) "MBEDTLS_SHA1_ALT", #endif /* MBEDTLS_SHA1_ALT */ @@ -117,6 +159,12 @@ static const char *features[] = { #if defined(MBEDTLS_SHA512_ALT) "MBEDTLS_SHA512_ALT", #endif /* MBEDTLS_SHA512_ALT */ +#if defined(MBEDTLS_XTEA_ALT) + "MBEDTLS_XTEA_ALT", +#endif /* MBEDTLS_XTEA_ALT */ +#if defined(MBEDTLS_ECP_ALT) + "MBEDTLS_ECP_ALT", +#endif /* MBEDTLS_ECP_ALT */ #if defined(MBEDTLS_MD2_PROCESS_ALT) "MBEDTLS_MD2_PROCESS_ALT", #endif /* MBEDTLS_MD2_PROCESS_ALT */ @@ -159,6 +207,48 @@ static const char *features[] = { #if defined(MBEDTLS_AES_DECRYPT_ALT) "MBEDTLS_AES_DECRYPT_ALT", #endif /* MBEDTLS_AES_DECRYPT_ALT */ +#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) + "MBEDTLS_ECDH_GEN_PUBLIC_ALT", +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ +#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) + "MBEDTLS_ECDH_COMPUTE_SHARED_ALT", +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + "MBEDTLS_ECDSA_VERIFY_ALT", +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + "MBEDTLS_ECDSA_SIGN_ALT", +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#if defined(MBEDTLS_ECDSA_GENKEY_ALT) + "MBEDTLS_ECDSA_GENKEY_ALT", +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + "MBEDTLS_ECP_INTERNAL_ALT", +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + "MBEDTLS_ECP_ADD_MIXED_ALT", +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + "MBEDTLS_ECP_DOUBLE_JAC_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ #if defined(MBEDTLS_TEST_NULL_ENTROPY) "MBEDTLS_TEST_NULL_ENTROPY", #endif /* MBEDTLS_TEST_NULL_ENTROPY */ @@ -168,6 +258,9 @@ static const char *features[] = { #if defined(MBEDTLS_AES_ROM_TABLES) "MBEDTLS_AES_ROM_TABLES", #endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_AES_FEWER_TABLES) + "MBEDTLS_AES_FEWER_TABLES", +#endif /* MBEDTLS_AES_FEWER_TABLES */ #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) "MBEDTLS_CAMELLIA_SMALL_MEMORY", #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ @@ -180,6 +273,12 @@ static const char *features[] = { #if defined(MBEDTLS_CIPHER_MODE_CTR) "MBEDTLS_CIPHER_MODE_CTR", #endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + "MBEDTLS_CIPHER_MODE_OFB", +#endif /* MBEDTLS_CIPHER_MODE_OFB */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + "MBEDTLS_CIPHER_MODE_XTS", +#endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) "MBEDTLS_CIPHER_NULL_CIPHER", #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ @@ -201,6 +300,9 @@ static const char *features[] = { #if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", #endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + "MBEDTLS_REMOVE_3DES_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) "MBEDTLS_ECP_DP_SECP192R1_ENABLED", #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ @@ -237,9 +339,15 @@ static const char *features[] = { #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) "MBEDTLS_ECP_DP_CURVE25519_ENABLED", #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + "MBEDTLS_ECP_DP_CURVE448_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_NIST_OPTIM) "MBEDTLS_ECP_NIST_OPTIM", #endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + "MBEDTLS_ECP_RESTARTABLE", +#endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) "MBEDTLS_ECDSA_DETERMINISTIC", #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ @@ -327,6 +435,9 @@ static const char *features[] = { #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) "MBEDTLS_SSL_ALL_ALERT_MESSAGES", #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + "MBEDTLS_SSL_ASYNC_PRIVATE", +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_DEBUG_ALL) "MBEDTLS_SSL_DEBUG_ALL", #endif /* MBEDTLS_SSL_DEBUG_ALL */ @@ -399,6 +510,9 @@ static const char *features[] = { #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) "MBEDTLS_SSL_TRUNCATED_HMAC", #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ #if defined(MBEDTLS_THREADING_ALT) "MBEDTLS_THREADING_ALT", #endif /* MBEDTLS_THREADING_ALT */ @@ -453,12 +567,21 @@ static const char *features[] = { #if defined(MBEDTLS_CAMELLIA_C) "MBEDTLS_CAMELLIA_C", #endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + "MBEDTLS_ARIA_C", +#endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_CCM_C) "MBEDTLS_CCM_C", #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CERTS_C) "MBEDTLS_CERTS_C", #endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CHACHA20_C) + "MBEDTLS_CHACHA20_C", +#endif /* MBEDTLS_CHACHA20_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + "MBEDTLS_CHACHAPOLY_C", +#endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_C) "MBEDTLS_CIPHER_C", #endif /* MBEDTLS_CIPHER_C */ @@ -501,9 +624,15 @@ static const char *features[] = { #if defined(MBEDTLS_HAVEGE_C) "MBEDTLS_HAVEGE_C", #endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_HKDF_C) + "MBEDTLS_HKDF_C", +#endif /* MBEDTLS_HKDF_C */ #if defined(MBEDTLS_HMAC_DRBG_C) "MBEDTLS_HMAC_DRBG_C", #endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_NIST_KW_C) + "MBEDTLS_NIST_KW_C", +#endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_MD_C) "MBEDTLS_MD_C", #endif /* MBEDTLS_MD_C */ @@ -555,6 +684,9 @@ static const char *features[] = { #if defined(MBEDTLS_PLATFORM_C) "MBEDTLS_PLATFORM_C", #endif /* MBEDTLS_PLATFORM_C */ +#if defined(MBEDTLS_POLY1305_C) + "MBEDTLS_POLY1305_C", +#endif /* MBEDTLS_POLY1305_C */ #if defined(MBEDTLS_RIPEMD160_C) "MBEDTLS_RIPEMD160_C", #endif /* MBEDTLS_RIPEMD160_C */ diff --git a/Externals/mbedtls/library/x509.c b/Externals/mbedtls/library/x509.c index fad390d857..52b5b649f7 100644 --- a/Externals/mbedtls/library/x509.c +++ b/Externals/mbedtls/library/x509.c @@ -59,26 +59,14 @@ #define mbedtls_snprintf snprintf #endif - #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include -#else +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_util.h" #include #endif -#if defined(MBEDTLS_FS_IO) -#include -#if !defined(_WIN32) -#include -#include -#include -#endif -#endif - #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } @@ -480,53 +468,129 @@ int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, } } -static int x509_parse_int(unsigned char **p, unsigned n, int *res){ +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ *res = 0; - for( ; n > 0; --n ){ - if( ( **p < '0') || ( **p > '9' ) ) return MBEDTLS_ERR_X509_INVALID_DATE; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + *res *= 10; - *res += (*(*p)++ - '0'); + *res += ( *(*p)++ - '0' ); } - return 0; + + return( 0 ); } -static int x509_date_is_valid(const mbedtls_x509_time *time) +static int x509_date_is_valid(const mbedtls_x509_time *t ) { int ret = MBEDTLS_ERR_X509_INVALID_DATE; + int month_len; - CHECK_RANGE( 0, 9999, time->year ); - CHECK_RANGE( 0, 23, time->hour ); - CHECK_RANGE( 0, 59, time->min ); - CHECK_RANGE( 0, 59, time->sec ); + CHECK_RANGE( 0, 9999, t->year ); + CHECK_RANGE( 0, 23, t->hour ); + CHECK_RANGE( 0, 59, t->min ); + CHECK_RANGE( 0, 59, t->sec ); - switch( time->mon ) + switch( t->mon ) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: - CHECK_RANGE( 1, 31, time->day ); + month_len = 31; break; case 4: case 6: case 9: case 11: - CHECK_RANGE( 1, 30, time->day ); + month_len = 30; break; case 2: - CHECK_RANGE( 1, 28 + (time->year % 4 == 0), time->day ); + if( ( !( t->year % 4 ) && t->year % 100 ) || + !( t->year % 400 ) ) + month_len = 29; + else + month_len = 28; break; default: return( ret ); } + CHECK_RANGE( 1, month_len, t->day ); return( 0 ); } +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *tm ) +{ + int ret; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &tm->year ) ); + if ( 2 == yearlen ) + { + if ( tm->year < 50 ) + tm->year += 100; + + tm->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &tm->mon ) ); + CHECK( x509_parse_int( p, 2, &tm->day ) ); + CHECK( x509_parse_int( p, 2, &tm->hour ) ); + CHECK( x509_parse_int( p, 2, &tm->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( tm ) ); + + return ( 0 ); +} + /* * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } */ int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, - mbedtls_x509_time *time ) + mbedtls_x509_time *tm ) { int ret; - size_t len; + size_t len, year_len; unsigned char tag; if( ( end - *p ) < 1 ) @@ -536,55 +600,20 @@ int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, tag = **p; if( tag == MBEDTLS_ASN1_UTC_TIME ) - { - (*p)++; - ret = mbedtls_asn1_get_len( p, end, &len ); - - if( ret != 0 ) - return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); - - CHECK( x509_parse_int( p, 2, &time->year ) ); - CHECK( x509_parse_int( p, 2, &time->mon ) ); - CHECK( x509_parse_int( p, 2, &time->day ) ); - CHECK( x509_parse_int( p, 2, &time->hour ) ); - CHECK( x509_parse_int( p, 2, &time->min ) ); - if( len > 10 ) - CHECK( x509_parse_int( p, 2, &time->sec ) ); - if( len > 12 && *(*p)++ != 'Z' ) - return( MBEDTLS_ERR_X509_INVALID_DATE ); - - time->year += 100 * ( time->year < 50 ); - time->year += 1900; - - CHECK( x509_date_is_valid( time ) ); - - return( 0 ); - } + year_len = 2; else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) - { - (*p)++; - ret = mbedtls_asn1_get_len( p, end, &len ); - - if( ret != 0 ) - return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); - - CHECK( x509_parse_int( p, 4, &time->year ) ); - CHECK( x509_parse_int( p, 2, &time->mon ) ); - CHECK( x509_parse_int( p, 2, &time->day ) ); - CHECK( x509_parse_int( p, 2, &time->hour ) ); - CHECK( x509_parse_int( p, 2, &time->min ) ); - if( len > 12 ) - CHECK( x509_parse_int( p, 2, &time->sec ) ); - if( len > 14 && *(*p)++ != 'Z' ) - return( MBEDTLS_ERR_X509_INVALID_DATE ); - - CHECK( x509_date_is_valid( time ) ); - - return( 0 ); - } + year_len = 4; else return( MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + return x509_parse_time( p, len, year_len, tm ); } int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) @@ -661,7 +690,7 @@ int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x50 /* * X.509 Extensions (No parsing of extensions, pointer should - * be either manually updated or extensions should be parsed! + * be either manually updated or extensions should be parsed!) */ int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext, int tag ) @@ -862,36 +891,14 @@ int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) * Set the time structure to the current time. * Return 0 on success, non-zero on failure. */ -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) static int x509_get_current_time( mbedtls_x509_time *now ) { - SYSTEMTIME st; - - GetSystemTime( &st ); - - now->year = st.wYear; - now->mon = st.wMonth; - now->day = st.wDay; - now->hour = st.wHour; - now->min = st.wMinute; - now->sec = st.wSecond; - - return( 0 ); -} -#else -static int x509_get_current_time( mbedtls_x509_time *now ) -{ - struct tm *lt; + struct tm *lt, tm_buf; mbedtls_time_t tt; int ret = 0; -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - tt = mbedtls_time( NULL ); - lt = gmtime( &tt ); + lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); if( lt == NULL ) ret = -1; @@ -905,14 +912,8 @@ static int x509_get_current_time( mbedtls_x509_time *now ) now->sec = lt->tm_sec; } -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - return( ret ); } -#endif /* _WIN32 && !EFIX64 && !EFI32 */ /* * Return 0 if before <= after, 1 otherwise @@ -1000,7 +1001,7 @@ int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) */ int mbedtls_x509_self_test( int verbose ) { -#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) int ret; uint32_t flags; mbedtls_x509_crt cacert; diff --git a/Externals/mbedtls/library/x509_create.c b/Externals/mbedtls/library/x509_create.c index df20ec8ebd..546e8fa1a9 100644 --- a/Externals/mbedtls/library/x509_create.c +++ b/Externals/mbedtls/library/x509_create.c @@ -33,48 +33,84 @@ #include +/* Structure linking OIDs for X.509 DN AttributeTypes to their + * string representations and default string encodings used by Mbed TLS. */ typedef struct { - const char *name; - size_t name_len; - const char*oid; + const char *name; /* String representation of AttributeType, e.g. + * "CN" or "emailAddress". */ + size_t name_len; /* Length of 'name', without trailing 0 byte. */ + const char *oid; /* String representation of OID of AttributeType, + * as per RFC 5280, Appendix A.1. */ + int default_tag; /* The default character encoding used for the + * given attribute type, e.g. + * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ } x509_attr_descriptor_t; #define ADD_STRLEN( s ) s, sizeof( s ) - 1 +/* X.509 DN attributes from RFC 5280, Appendix A.1. */ static const x509_attr_descriptor_t x509_attrs[] = { - { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, - { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, - { ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY }, - { ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY }, - { ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION }, - { ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION }, - { ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY }, - { ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY }, - { ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL }, - { ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT }, - { ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT }, - { ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE }, - { ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE }, - { ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL }, - { ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER }, - { ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS }, - { ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE }, - { ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER }, - { ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE }, - { ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME }, - { ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME }, - { ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME }, - { ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME }, - { ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS }, - { ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM }, - { ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER }, - { ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT }, - { ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT }, - { NULL, 0, NULL } + { ADD_STRLEN( "CN" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "commonName" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "C" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "countryName" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "O" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationName" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "L" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "locality" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "R" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "OU" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationalUnitName" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "ST" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "stateOrProvinceName" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "emailAddress" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "serialNumber" ), + MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalAddress" ), + MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalCode" ), + MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "dnQualifier" ), + MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "title" ), + MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "surName" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "SN" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "givenName" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "GN" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "initials" ), + MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "pseudonym" ), + MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "generationQualifier" ), + MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "domainComponent" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "DC" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { NULL, 0, NULL, MBEDTLS_ASN1_NULL } }; -static const char *x509_at_oid_from_name( const char *name, size_t name_len ) +static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len ) { const x509_attr_descriptor_t *cur; @@ -83,7 +119,10 @@ static const char *x509_at_oid_from_name( const char *name, size_t name_len ) strncmp( cur->name, name, name_len ) == 0 ) break; - return( cur->oid ); + if ( cur->name == NULL ) + return( NULL ); + + return( cur ); } int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) @@ -92,6 +131,7 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na const char *s = name, *c = s; const char *end = s + strlen( s ); const char *oid = NULL; + const x509_attr_descriptor_t* attr_descr = NULL; int in_tag = 1; char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; char *d = data; @@ -103,12 +143,13 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na { if( in_tag && *c == '=' ) { - if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) + if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL ) { ret = MBEDTLS_ERR_X509_UNKNOWN_OID; goto exit; } + oid = attr_descr->oid; s = c + 1; in_tag = 0; d = data; @@ -127,13 +168,19 @@ int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *na } else if( !in_tag && ( *c == ',' || c == end ) ) { - if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ), - (unsigned char *) data, - d - data ) == NULL ) + mbedtls_asn1_named_data* cur = + mbedtls_asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ); + + if(cur == NULL ) { return( MBEDTLS_ERR_X509_ALLOC_FAILED ); } + // set tagType + cur->val.tag = attr_descr->default_tag; + while( c < end && *(c + 1) == ' ' ) c++; @@ -192,46 +239,40 @@ int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, * * AttributeValue ::= ANY DEFINED BY AttributeType */ -static int x509_write_name( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - const unsigned char *name, size_t name_len ) +static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name) { int ret; size_t len = 0; + const char *oid = (const char*)cur_name->oid.p; + size_t oid_len = cur_name->oid.len; + const unsigned char *name = cur_name->val.p; + size_t name_len = cur_name->val.len; - // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL - // - if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len && - memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start, - (const char *) name, - name_len ) ); - } - else - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start, - (const char *) name, - name_len ) ); - } - + // Write correct string tag and value + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start, + cur_name->val.tag, + (const char *) name, + name_len ) ); // Write OID // - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, + oid_len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ); return( (int) len ); } int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ) + mbedtls_asn1_named_data *first ) { int ret; size_t len = 0; @@ -239,9 +280,7 @@ int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, while( cur != NULL ) { - MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, - cur->oid.len, - cur->val.p, cur->val.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) ); cur = cur->next; } diff --git a/Externals/mbedtls/library/x509_crl.c b/Externals/mbedtls/library/x509_crl.c index 7b2b4733bc..8450f87e03 100644 --- a/Externals/mbedtls/library/x509_crl.c +++ b/Externals/mbedtls/library/x509_crl.c @@ -39,6 +39,7 @@ #include "mbedtls/x509_crl.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include @@ -66,11 +67,6 @@ #include #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Version ::= INTEGER { v1(0), v2(1) } */ @@ -95,17 +91,23 @@ static int x509_crl_get_version( unsigned char **p, } /* - * X.509 CRL v2 extensions (no extensions parsed yet.) + * X.509 CRL v2 extensions + * + * We currently don't parse any extension's content, but we do check that the + * list of extensions is well-formed and abort on critical extensions (that + * are unsupported as we don't support any extension so far) */ static int x509_get_crl_ext( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext ) { int ret; - size_t len = 0; - /* Get explicit tag */ - if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 ) + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) { if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) return( 0 ); @@ -115,11 +117,54 @@ static int x509_get_crl_ext( unsigned char **p, while( *p < end ) { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + int is_critical = 0; + const unsigned char *end_ext_data; + size_t len; + + /* Get enclosing sequence tag */ if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + end_ext_data = *p + len; + + /* Get OID (currently ignored) */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } *p += len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, + &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Ignore data so far and just check its length */ + *p += len; + if( *p != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Abort on (unsupported) critical extensions */ + if( is_critical ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); } if( *p != end ) @@ -257,7 +302,7 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, { int ret; size_t len; - unsigned char *p, *end; + unsigned char *p = NULL, *end = NULL; mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; mbedtls_x509_crl *crl = chain; @@ -294,7 +339,11 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, /* * Copy raw DER-encoded CRL */ - if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL ) + if( buflen == 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + p = mbedtls_calloc( 1, buflen ); + if( p == NULL ) return( MBEDTLS_ERR_X509_ALLOC_FAILED ); memcpy( p, buf, buflen ); @@ -352,14 +401,14 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, return( ret ); } - crl->version++; - - if( crl->version > 2 ) + if( crl->version < 0 || crl->version > 1 ) { mbedtls_x509_crl_free( crl ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); } + crl->version++; + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, &crl->sig_md, &crl->sig_pk, &crl->sig_opts ) ) != 0 ) @@ -525,16 +574,17 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s if( ( ret = mbedtls_x509_crl_parse_der( chain, pem.buf, pem.buflen ) ) != 0 ) { + mbedtls_pem_free( &pem ); return( ret ); } - - mbedtls_pem_free( &pem ); } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + else if( is_pem ) { mbedtls_pem_free( &pem ); return( ret ); } + + mbedtls_pem_free( &pem ); } /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. * And a valid CRL cannot be less than 1 byte anyway. */ @@ -562,7 +612,7 @@ int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) ret = mbedtls_x509_crl_parse( chain, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -683,7 +733,7 @@ void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) { name_prv = name_cur; name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } @@ -692,13 +742,14 @@ void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) { entry_prv = entry_cur; entry_cur = entry_cur->next; - mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_platform_zeroize( entry_prv, + sizeof( mbedtls_x509_crl_entry ) ); mbedtls_free( entry_prv ); } if( crl_cur->raw.p != NULL ) { - mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len ); mbedtls_free( crl_cur->raw.p ); } @@ -712,7 +763,7 @@ void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) crl_prv = crl_cur; crl_cur = crl_cur->next; - mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); if( crl_prv != crl ) mbedtls_free( crl_prv ); } diff --git a/Externals/mbedtls/library/x509_crt.c b/Externals/mbedtls/library/x509_crt.c index 60e14f90e7..325bbc0b10 100644 --- a/Externals/mbedtls/library/x509_crt.c +++ b/Externals/mbedtls/library/x509_crt.c @@ -27,6 +27,8 @@ * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf */ #if !defined(MBEDTLS_CONFIG_FILE) @@ -39,8 +41,8 @@ #include "mbedtls/x509_crt.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" -#include #include #if defined(MBEDTLS_PEM_PARSE_C) @@ -50,6 +52,7 @@ #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else +#include #include #define mbedtls_free free #define mbedtls_calloc calloc @@ -75,19 +78,29 @@ #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} +/* + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} x509_crt_verify_chain_item; + +/* + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) /* * Default profile */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = { - /* Hashes from SHA-1 and above */ +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) + /* Allow SHA-1 (weak, but still safe in controlled environments) */ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) | +#endif + /* Only SHA-2 hashes */ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | @@ -131,7 +144,8 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), /* Only ECDSA */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ), + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), #if defined(MBEDTLS_ECP_C) /* Only NIST P-256 and P-384 */ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | @@ -144,11 +158,14 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = /* * Check md_alg against profile - * Return 0 if md_alg acceptable for this profile, -1 otherwise + * Return 0 if md_alg is acceptable for this profile, -1 otherwise */ static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, mbedtls_md_type_t md_alg ) { + if( md_alg == MBEDTLS_MD_NONE ) + return( -1 ); + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) return( 0 ); @@ -157,11 +174,14 @@ static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, /* * Check pk_alg against profile - * Return 0 if pk_alg acceptable for this profile, -1 otherwise + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise */ static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, mbedtls_pk_type_t pk_alg ) { + if( pk_alg == MBEDTLS_PK_NONE ) + return( -1 ); + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) return( 0 ); @@ -170,12 +190,13 @@ static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, /* * Check key against profile - * Return 0 if pk_alg acceptable for this profile, -1 otherwise + * Return 0 if pk is acceptable for this profile, -1 otherwise */ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg, const mbedtls_pk_context *pk ) { + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk ); + #if defined(MBEDTLS_RSA_C) if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) { @@ -191,7 +212,10 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) { - mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + + if( gid == MBEDTLS_ECP_DP_NONE ) + return( -1 ); if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) return( 0 ); @@ -203,6 +227,153 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, return( -1 ); } +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + /* We can't have a match if there is no wildcard to match */ + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( -1 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Reset (init or clear) a verify_chain + */ +static void x509_crt_verify_chain_reset( + mbedtls_x509_crt_verify_chain *ver_chain ) +{ + size_t i; + + for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ ) + { + ver_chain->items[i].crt = NULL; + ver_chain->items[i].flags = (uint32_t) -1; + } + + ver_chain->len = 0; +} + /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ @@ -470,9 +641,12 @@ static int x509_get_subject_alt_name( unsigned char **p, if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - if( ( tag & MBEDTLS_ASN1_CONTEXT_SPECIFIC ) != MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + { return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } /* Skip everything but DNS name */ if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) @@ -552,18 +726,14 @@ static int x509_get_crt_ext( unsigned char **p, end_ext_data = *p + len; /* Get extension ID */ - extn_oid.tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID ) ) != 0 ) return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + extn_oid.tag = MBEDTLS_ASN1_OID; extn_oid.p = *p; *p += extn_oid.len; - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - /* Get optional critical */ if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) @@ -711,7 +881,7 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char * memcpy( p, buf, crt->raw.len ); - // Direct pointers to the new buffer + // Direct pointers to the new buffer p += crt->raw.len - len; end = crt_end = p + len; @@ -746,14 +916,14 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char * return( ret ); } - crt->version++; - - if( crt->version > 3 ) + if( crt->version < 0 || crt->version > 2 ) { mbedtls_x509_crt_free( crt ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); } + crt->version++; + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, &crt->sig_md, &crt->sig_pk, &crt->sig_opts ) ) != 0 ) @@ -969,8 +1139,8 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu */ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) { - int success = 0, first_error = 0, total_failed = 0; #if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; int buf_format = MBEDTLS_X509_FORMAT_DER; #endif @@ -1093,7 +1263,7 @@ int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) ret = mbedtls_x509_crt_parse( chain, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -1122,7 +1292,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) p = filename + len; filename[len++] = '*'; - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, len, szDir, + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, MAX_PATH - 3 ); if( w_ret == 0 ) return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); @@ -1144,7 +1314,10 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) p, (int) len - 1, NULL, NULL ); if( w_ret == 0 ) - return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } w_ret = mbedtls_x509_crt_parse_file( chain, filename ); if( w_ret < 0 ) @@ -1157,6 +1330,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) if( GetLastError() != ERROR_NO_MORE_FILES ) ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; +cleanup: FindClose( hFind ); #else /* _WIN32 */ int t_ret; @@ -1169,13 +1343,13 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) if( dir == NULL ) return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); -#if defined(MBEDTLS_THREADING_PTHREAD) +#if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) { closedir( dir ); return( ret ); } -#endif +#endif /* MBEDTLS_THREADING_C */ while( ( entry = readdir( dir ) ) != NULL ) { @@ -1208,10 +1382,10 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) cleanup: closedir( dir ); -#if defined(MBEDTLS_THREADING_PTHREAD) +#if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; -#endif +#endif /* MBEDTLS_THREADING_C */ #endif /* _WIN32 */ @@ -1624,7 +1798,7 @@ int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509 /* * Check that the given certificate is not revoked according to the CRL. - * Skip validation is no CRL for the given CA is present. + * Skip validation if no CRL for the given CA is present. */ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, mbedtls_x509_crl *crl_list, @@ -1640,9 +1814,7 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, while( crl_list != NULL ) { if( crl_list->version == 0 || - crl_list->issuer_raw.len != ca->subject_raw.len || - memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, - crl_list->issuer_raw.len ) != 0 ) + x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) { crl_list = crl_list->next; continue; @@ -1652,7 +1824,8 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, * Check if the CA is configured to sign CRLs */ #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + if( mbedtls_x509_crt_check_key_usage( ca, + MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) { flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; @@ -1669,18 +1842,14 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, flags |= MBEDTLS_X509_BADCRL_BAD_PK; md_info = mbedtls_md_info_from_type( crl_list->sig_md ); - if( md_info == NULL ) + if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) { - /* - * Cannot check 'unknown' hash - */ + /* Note: this can't happen except after an internal error */ flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } - mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); - - if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 ) + if( x509_profile_check_key( profile, &ca->pk ) != 0 ) flags |= MBEDTLS_X509_BADCERT_BAD_KEY; if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, @@ -1717,132 +1886,40 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, #endif /* MBEDTLS_X509_CRL_PARSE_C */ /* - * Like memcmp, but case-insensitive and always returns -1 if different + * Check the signature of a certificate by its parent */ -static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +static int x509_crt_check_signature( const mbedtls_x509_crt *child, + mbedtls_x509_crt *parent, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { - size_t i; - unsigned char diff; - const unsigned char *n1 = s1, *n2 = s2; + const mbedtls_md_info_t *md_info; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - for( i = 0; i < len; i++ ) + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) { - diff = n1[i] ^ n2[i]; - - if( diff == 0 ) - continue; - - if( diff == 32 && - ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || - ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) - { - continue; - } - + /* Note: this can't happen except after an internal error */ return( -1 ); } - return( 0 ); -} - -/* - * Return 0 if name matches wildcard, -1 otherwise - */ -static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name ) -{ - size_t i; - size_t cn_idx = 0, cn_len = strlen( cn ); - - if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) - return( 0 ); - - for( i = 0; i < cn_len; ++i ) - { - if( cn[i] == '.' ) - { - cn_idx = i; - break; - } - } - - if( cn_idx == 0 ) + /* Skip expensive computation on obvious mismatch */ + if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) return( -1 ); - if( cn_len - cn_idx == name->len - 1 && - x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) { - return( 0 ); + return( mbedtls_pk_verify_restartable( &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len, &rs_ctx->pk ) ); } +#else + (void) rs_ctx; +#endif - return( -1 ); -} - -/* - * Compare two X.509 strings, case-insensitive, and allowing for some encoding - * variations (but not all). - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) -{ - if( a->tag == b->tag && - a->len == b->len && - memcmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - a->len == b->len && - x509_memcasecmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - return( -1 ); -} - -/* - * Compare two X.509 Names (aka rdnSequence). - * - * See RFC 5280 section 7.1, though we don't implement the whole algorithm: - * we sometimes return unequal when the full algorithm would return equal, - * but never the other way. (In particular, we don't do Unicode normalisation - * or space folding.) - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) -{ - /* Avoid recursion, it might not be optimised by the compiler */ - while( a != NULL || b != NULL ) - { - if( a == NULL || b == NULL ) - return( -1 ); - - /* type */ - if( a->oid.tag != b->oid.tag || - a->oid.len != b->oid.len || - memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) - { - return( -1 ); - } - - /* value */ - if( x509_string_cmp( &a->val, &b->val ) != 0 ) - return( -1 ); - - /* structure of the list of sets */ - if( a->next_merged != b->next_merged ) - return( -1 ); - - a = a->next; - b = b->next; - } - - /* a == NULL == b */ - return( 0 ); + return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) ); } /* @@ -1850,11 +1927,10 @@ static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b * Return 0 if yes, -1 if not. * * top means parent is a locally-trusted certificate - * bottom means child is the end entity cert */ static int x509_crt_check_parent( const mbedtls_x509_crt *child, const mbedtls_x509_crt *parent, - int top, int bottom ) + int top ) { int need_ca_bit; @@ -1869,14 +1945,6 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, if( top && parent->version < 3 ) need_ca_bit = 0; - /* Exception: self-signed end-entity certs that are locally trusted. */ - if( top && bottom && - child->raw.len == parent->raw.len && - memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) - { - need_ca_bit = 0; - } - if( need_ca_bit && ! parent->ca_istrue ) return( -1 ); @@ -1891,274 +1959,541 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, return( 0 ); } -static int x509_crt_verify_top( - mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - int path_cnt, int self_cnt, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) +/* + * Find a suitable parent for child in candidates, or return NULL. + * + * Here suitable is defined as: + * 1. subject name matches child's issuer + * 2. if necessary, the CA bit is set and key usage allows signing certs + * 3. for trusted roots, the signature is correct + * (for intermediates, the signature is checked and the result reported) + * 4. pathlen constraints are satisfied + * + * If there's a suitable candidate which is also time-valid, return the first + * such. Otherwise, return the first suitable candidate (or NULL if there is + * none). + * + * The rationale for this rule is that someone could have a list of trusted + * roots with two versions on the same root with different validity periods. + * (At least one user reported having such a list and wanted it to just work.) + * The reason we don't just require time-validity is that generally there is + * only one version, and if it's expired we want the flags to state that + * rather than NOT_TRUSTED, as would be the case if we required it here. + * + * The rationale for rule 3 (signature for trusted roots) is that users might + * have two versions of the same CA with different keys in their list, and the + * way we select the correct one is by checking the signature (as we don't + * rely on key identifier extensions). (This is one way users might choose to + * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent + * - [in] candidates: chained list of potential parents + * - [out] r_parent: parent found (or NULL) + * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top + * of the chain, 0 otherwise + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will never be greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent_in( + mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + mbedtls_x509_crt **r_parent, + int *r_signature_is_good, + int top, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { int ret; - uint32_t ca_flags = 0; - int check_path_cnt; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; + mbedtls_x509_crt *parent, *fallback_parent; + int signature_is_good, fallback_signature_is_good; - if( mbedtls_x509_time_is_past( &child->valid_to ) ) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if( mbedtls_x509_time_is_future( &child->valid_from ) ) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - - if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - - if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - /* - * Child is the top of the chain. Check against the trust_ca list. - */ - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - - md_info = mbedtls_md_info_from_type( child->sig_md ); - if( md_info == NULL ) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* did we have something in progress? */ + if( rs_ctx != NULL && rs_ctx->parent != NULL ) { - /* - * Cannot check 'unknown', no need to try any CA - */ - trust_ca = NULL; + /* restore saved state */ + parent = rs_ctx->parent; + fallback_parent = rs_ctx->fallback_parent; + fallback_signature_is_good = rs_ctx->fallback_signature_is_good; + + /* clear saved state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_signature_is_good = 0; + + /* resume where we left */ + goto check_signature; } - else - mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); +#endif - for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) + fallback_parent = NULL; + fallback_signature_is_good = 0; + + for( parent = candidates; parent != NULL; parent = parent->next ) { - if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) + /* basic parenting skills (name, CA bit, key usage) */ + if( x509_crt_check_parent( child, parent, top ) != 0 ) continue; - check_path_cnt = path_cnt + 1; - - /* - * Reduce check_path_cnt to check against if top of the chain is - * the same as the trusted CA - */ - if( child->subject_raw.len == trust_ca->subject_raw.len && - memcmp( child->subject_raw.p, trust_ca->subject_raw.p, - child->issuer_raw.len ) == 0 ) - { - check_path_cnt--; - } - - /* Self signed certificates do not count towards the limit */ - if( trust_ca->max_pathlen > 0 && - trust_ca->max_pathlen < check_path_cnt - self_cnt ) + /* +1 because stored max_pathlen is 1 higher that the actual value */ + if( parent->max_pathlen > 0 && + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) { continue; } - if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ) + /* Signature */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +check_signature: +#endif + ret = x509_crt_check_signature( child, parent, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { + /* save state */ + rs_ctx->parent = parent; + rs_ctx->fallback_parent = fallback_parent; + rs_ctx->fallback_signature_is_good = fallback_signature_is_good; + + return( ret ); + } +#else + (void) ret; +#endif + + signature_is_good = ret == 0; + if( top && ! signature_is_good ) + continue; + + /* optional time check */ + if( mbedtls_x509_time_is_past( &parent->valid_to ) || + mbedtls_x509_time_is_future( &parent->valid_from ) ) + { + if( fallback_parent == NULL ) + { + fallback_parent = parent; + fallback_signature_is_good = signature_is_good; + } + continue; } - if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) - { - continue; - } - - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) - { - continue; - } - - /* - * Top of chain is signed by a trusted CA - */ - *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; - - if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - break; } - /* - * If top of chain is not the same as the trusted CA send a verify request - * to the callback for any issues with validity and CRL presence for the - * trusted CA certificate. - */ - if( trust_ca != NULL && - ( child->subject_raw.len != trust_ca->subject_raw.len || - memcmp( child->subject_raw.p, trust_ca->subject_raw.p, - child->issuer_raw.len ) != 0 ) ) + if( parent != NULL ) { -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the chain's top crt */ - *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); -#else - ((void) ca_crl); -#endif - - if( NULL != f_vrfy ) - { - if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, - &ca_flags ) ) != 0 ) - { - return( ret ); - } - } - } - - /* Call callback on top cert */ - if( NULL != f_vrfy ) - { - if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) - return( ret ); - } - - *flags |= ca_flags; - - return( 0 ); -} - -static int x509_crt_verify_child( - mbedtls_x509_crt *child, mbedtls_x509_crt *parent, - mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - int path_cnt, int self_cnt, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - int ret; - uint32_t parent_flags = 0; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - mbedtls_x509_crt *grandparent; - const mbedtls_md_info_t *md_info; - - /* Counting intermediate self signed certificates */ - if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) - self_cnt++; - - /* path_cnt is 0 for the first intermediate CA */ - if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) - { - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); - } - - if( mbedtls_x509_time_is_past( &child->valid_to ) ) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if( mbedtls_x509_time_is_future( &child->valid_from ) ) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - - if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - - if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - md_info = mbedtls_md_info_from_type( child->sig_md ); - if( md_info == NULL ) - { - /* - * Cannot check 'unknown' hash - */ - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + *r_parent = parent; + *r_signature_is_good = signature_is_good; } else { - mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); - - if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) - { - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - } + *r_parent = fallback_parent; + *r_signature_is_good = fallback_signature_is_good; } -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the given crt */ - *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile ); -#endif - - /* Look for a grandparent in trusted CAs */ - for( grandparent = trust_ca; - grandparent != NULL; - grandparent = grandparent->next ) - { - if( x509_crt_check_parent( parent, grandparent, - 0, path_cnt == 0 ) == 0 ) - break; - } - - if( grandparent != NULL ) - { - ret = x509_crt_verify_top( parent, grandparent, ca_crl, profile, - path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - /* Look for a grandparent upwards the chain */ - for( grandparent = parent->next; - grandparent != NULL; - grandparent = grandparent->next ) - { - /* +2 because the current step is not yet accounted for - * and because max_pathlen is one higher than it should be. - * Also self signed certificates do not count to the limit. */ - if( grandparent->max_pathlen > 0 && - grandparent->max_pathlen < 2 + path_cnt - self_cnt ) - { - continue; - } - - if( x509_crt_check_parent( parent, grandparent, - 0, path_cnt == 0 ) == 0 ) - break; - } - - /* Is our parent part of the chain or at the top? */ - if( grandparent != NULL ) - { - ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, - profile, path_cnt + 1, self_cnt, &parent_flags, - f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, - path_cnt + 1, self_cnt, &parent_flags, - f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - } - - /* child is verified to be a child of the parent, call verify callback */ - if( NULL != f_vrfy ) - if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) - return( ret ); - - *flags |= parent_flags; - return( 0 ); } /* - * Verify the certificate validity + * Find a parent in trusted CAs or the provided chain, or return NULL. + * + * Searches in trusted CAs first, and return the first suitable parent found + * (see find_parent_in() for definition of suitable). + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent, followed + * by a chain of possible intermediates + * - [in] trust_ca: list of locally trusted certificates + * - [out] parent: parent found (or NULL) + * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 + * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * - [in] self_cnt: number of self-signed certs in the chain so far + * (will always be no greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent( + mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crt **parent, + int *parent_is_trusted, + int *signature_is_good, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_x509_crt *search_list; + + *parent_is_trusted = 1; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore then clear saved state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 ) + { + *parent_is_trusted = rs_ctx->parent_is_trusted; + rs_ctx->parent_is_trusted = -1; + } +#endif + + while( 1 ) { + search_list = *parent_is_trusted ? trust_ca : child->next; + + ret = x509_crt_find_parent_in( child, search_list, + parent, signature_is_good, + *parent_is_trusted, + path_cnt, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent_is_trusted = *parent_is_trusted; + return( ret ); + } +#else + (void) ret; +#endif + + /* stop here if found or already in second iteration */ + if( *parent != NULL || *parent_is_trusted == 0 ) + break; + + /* prepare second iteration */ + *parent_is_trusted = 0; + } + + /* extra precaution against mistakes in the caller */ + if( *parent == NULL ) + { + *parent_is_trusted = 0; + *signature_is_good = 0; + } + + return( 0 ); +} + +/* + * Check if an end-entity certificate is locally trusted + * + * Currently we require such certificates to be self-signed (actually only + * check for self-issued as self-signatures are not checked) + */ +static int x509_crt_check_ee_locally_trusted( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca ) +{ + mbedtls_x509_crt *cur; + + /* must be self-issued */ + if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) + return( -1 ); + + /* look for an exact match with trusted cert */ + for( cur = trust_ca; cur != NULL; cur = cur->next ) + { + if( crt->raw.len == cur->raw.len && + memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 ) + { + return( 0 ); + } + } + + /* too bad */ + return( -1 ); +} + +/* + * Build and verify a certificate chain + * + * Given a peer-provided list of certificates EE, C1, ..., Cn and + * a list of trusted certs R1, ... Rp, try to build and verify a chain + * EE, Ci1, ... Ciq [, Rj] + * such that every cert in the chain is a child of the next one, + * jumping to a trusted root as early as possible. + * + * Verify that chain and return it with flags for all issues found. + * + * Special cases: + * - EE == Rj -> return a one-element list containing it + * - EE, Ci1, ..., Ciq cannot be continued with a trusted root + * -> return that chain with NOT_TRUSTED set on Ciq + * + * Tests for (aspects of) this function should include at least: + * - trusted EE + * - EE -> trusted root + * - EE -> intermedate CA -> trusted root + * - if relevant: EE untrusted + * - if relevant: EE -> intermediate, untrusted + * with the aspect under test checked at each relevant level (EE, int, root). + * For some aspects longer chains are required, but usually length 2 is + * enough (but length 1 is not in general). + * + * Arguments: + * - [in] crt: the cert list EE, C1, ..., Cn + * - [in] trust_ca: the trusted list R1, ..., Rp + * - [in] ca_crl, profile: as in verify_with_profile() + * - [out] ver_chain: the built and verified chain + * Only valid when return value is 0, may contain garbage otherwise! + * Restart note: need not be the same when calling again to resume. + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - non-zero if the chain could not be fully built and examined + * - 0 is the chain was successfully built and examined, + * even if it was found to be invalid + */ +static int x509_crt_verify_chain( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + mbedtls_x509_crt_verify_chain *ver_chain, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + /* Don't initialize any of those variables here, so that the compiler can + * catch potential issues with jumping ahead when restarting */ + int ret; + uint32_t *flags; + mbedtls_x509_crt_verify_chain_item *cur; + mbedtls_x509_crt *child; + mbedtls_x509_crt *parent; + int parent_is_trusted; + int child_is_trusted; + int signature_is_good; + unsigned self_cnt; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* resume if we had an operation in progress */ + if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent ) + { + /* restore saved state */ + *ver_chain = rs_ctx->ver_chain; /* struct copy */ + self_cnt = rs_ctx->self_cnt; + + /* restore derived state */ + cur = &ver_chain->items[ver_chain->len - 1]; + child = cur->crt; + flags = &cur->flags; + + goto find_parent; + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + child = crt; + self_cnt = 0; + parent_is_trusted = 0; + child_is_trusted = 0; + + while( 1 ) { + /* Add certificate to the verification chain */ + cur = &ver_chain->items[ver_chain->len]; + cur->crt = child; + cur->flags = 0; + ver_chain->len++; + flags = &cur->flags; + + /* Check time-validity (all certificates) */ + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + /* Stop here for trusted roots (but not for trusted EE certs) */ + if( child_is_trusted ) + return( 0 ); + + /* Check signature algorithm: MD & PK algs */ + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* Special case: EE certs that are locally trusted */ + if( ver_chain->len == 1 && + x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) + { + return( 0 ); + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +find_parent: +#endif + /* Look for a parent in trusted CAs or up the chain */ + ret = x509_crt_find_parent( child, trust_ca, &parent, + &parent_is_trusted, &signature_is_good, + ver_chain->len - 1, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->in_progress = x509_crt_rs_find_parent; + rs_ctx->self_cnt = self_cnt; + rs_ctx->ver_chain = *ver_chain; /* struct copy */ + + return( ret ); + } +#else + (void) ret; +#endif + + /* No parent? We're done here */ + if( parent == NULL ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return( 0 ); + } + + /* Count intermediate self-issued (not necessarily self-signed) certs. + * These can occur with some strategies for key rollover, see [SIRO], + * and should be excluded from max_pathlen checks. */ + if( ver_chain->len != 1 && + x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + { + self_cnt++; + } + + /* path_cnt is 0 for the first intermediate CA, + * and if parent is trusted it's not an intermediate CA */ + if( ! parent_is_trusted && + ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately to avoid overflow the chain array */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + /* signature was checked while searching parent */ + if( ! signature_is_good ) + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + /* check size of signing key */ + if( x509_profile_check_key( profile, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); +#else + (void) ca_crl; +#endif + + /* prepare for next iteration */ + child = parent; + parent = NULL; + child_is_trusted = parent_is_trusted; + signature_is_good = 0; + } +} + +/* + * Check for CN match + */ +static int x509_crt_check_cn( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + /* try exact match */ + if( name->len == cn_len && + x509_memcasecmp( cn, name->p, cn_len ) == 0 ) + { + return( 0 ); + } + + /* try wildcard match */ + if( x509_check_wildcard( cn, name ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Verify the requested CN - only call this if cn is not NULL! + */ +static void x509_crt_verify_name( const mbedtls_x509_crt *crt, + const char *cn, + uint32_t *flags ) +{ + const mbedtls_x509_name *name; + const mbedtls_x509_sequence *cur; + size_t cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next ) + { + if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 ) + break; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + for( name = &crt->subject; name != NULL; name = name->next ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 && + x509_crt_check_cn( &name->val, cn, cn_len ) == 0 ) + { + break; + } + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } +} + +/* + * Merge the flags for all certs in the chain, after calling callback + */ +static int x509_crt_merge_flags_with_cb( + uint32_t *flags, + const mbedtls_x509_crt_verify_chain *ver_chain, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + unsigned i; + uint32_t cur_flags; + const mbedtls_x509_crt_verify_chain_item *cur; + + for( i = ver_chain->len; i != 0; --i ) + { + cur = &ver_chain->items[i-1]; + cur_flags = cur->flags; + + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 ) + return( ret ); + + *flags |= cur_flags; + } + + return( 0 ); +} + +/* + * Verify the certificate validity (default profile, not restartable) */ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -2167,13 +2502,13 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, - &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); + return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, + &mbedtls_x509_crt_profile_default, cn, flags, + f_vrfy, p_vrfy, NULL ) ); } - /* - * Verify the certificate validity, with profile + * Verify the certificate validity (user-chosen profile, not restartable) */ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -2183,116 +2518,86 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - size_t cn_len; - int ret; - int pathlen = 0, selfsigned = 0; - mbedtls_x509_crt *parent; - mbedtls_x509_name *name; - mbedtls_x509_sequence *cur = NULL; - mbedtls_pk_type_t pk_type; + return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, + profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); +} - if( profile == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +/* + * Verify the certificate validity, with profile, restartable version + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret; + mbedtls_pk_type_t pk_type; + mbedtls_x509_crt_verify_chain ver_chain; + uint32_t ee_flags; *flags = 0; + ee_flags = 0; + x509_crt_verify_chain_reset( &ver_chain ); - if( cn != NULL ) + if( profile == NULL ) { - name = &crt->subject; - cn_len = strlen( cn ); - - if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) - { - cur = &crt->subject_alt_names; - - while( cur != NULL ) - { - if( cur->buf.len == cn_len && - x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 ) - break; - - if( cur->buf.len > 2 && - memcmp( cur->buf.p, "*.", 2 ) == 0 && - x509_check_wildcard( cn, &cur->buf ) == 0 ) - { - break; - } - - cur = cur->next; - } - - if( cur == NULL ) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - else - { - while( name != NULL ) - { - if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 ) - { - if( name->val.len == cn_len && - x509_memcasecmp( name->val.p, cn, cn_len ) == 0 ) - break; - - if( name->val.len > 2 && - memcmp( name->val.p, "*.", 2 ) == 0 && - x509_check_wildcard( cn, &name->val ) == 0 ) - break; - } - - name = name->next; - } - - if( name == NULL ) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; } + /* check name if requested */ + if( cn != NULL ) + x509_crt_verify_name( crt, cn, &ee_flags ); + /* Check the type and size of the key */ pk_type = mbedtls_pk_get_type( &crt->pk ); if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; - if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + if( x509_profile_check_key( profile, &crt->pk ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - /* Look for a parent in trusted CAs */ - for( parent = trust_ca; parent != NULL; parent = parent->next ) + /* Check the chain */ + ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, + &ver_chain, rs_ctx ); + + if( ret != 0 ) + goto exit; + + /* Merge end-entity flags */ + ver_chain.items[0].flags |= ee_flags; + + /* Build final flags, calling callback on the way if any */ + ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); + +exit: +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_x509_crt_restart_free( rs_ctx ); +#endif + + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + + if( ret != 0 ) { - if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) - break; - } - - if( parent != NULL ) - { - ret = x509_crt_verify_top( crt, parent, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - /* Look for a parent upwards the chain */ - for( parent = crt->next; parent != NULL; parent = parent->next ) - if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) - break; - - /* Are we part of the chain or at the top? */ - if( parent != NULL ) - { - ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } + *flags = (uint32_t) -1; + return( ret ); } if( *flags != 0 ) @@ -2337,7 +2642,7 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) { name_prv = name_cur; name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } @@ -2346,7 +2651,7 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) { name_prv = name_cur; name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } @@ -2355,7 +2660,8 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) { seq_prv = seq_cur; seq_cur = seq_cur->next; - mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); mbedtls_free( seq_prv ); } @@ -2364,13 +2670,14 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) { seq_prv = seq_cur; seq_cur = seq_cur->next; - mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); mbedtls_free( seq_prv ); } if( cert_cur->raw.p != NULL ) { - mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len ); mbedtls_free( cert_cur->raw.p ); } @@ -2384,11 +2691,43 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) cert_prv = cert_cur; cert_cur = cert_cur->next; - mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); if( cert_prv != crt ) mbedtls_free( cert_prv ); } while( cert_cur != NULL ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) +{ + mbedtls_pk_restart_init( &ctx->pk ); + + ctx->parent = NULL; + ctx->fallback_parent = NULL; + ctx->fallback_signature_is_good = 0; + + ctx->parent_is_trusted = -1; + + ctx->in_progress = x509_crt_rs_none; + ctx->self_cnt = 0; + x509_crt_verify_chain_reset( &ctx->ver_chain ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_pk_restart_free( &ctx->pk ); + mbedtls_x509_crt_restart_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + #endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/Externals/mbedtls/library/x509_csr.c b/Externals/mbedtls/library/x509_csr.c index 603d06b64f..c8c08c87b2 100644 --- a/Externals/mbedtls/library/x509_csr.c +++ b/Externals/mbedtls/library/x509_csr.c @@ -39,6 +39,7 @@ #include "mbedtls/x509_csr.h" #include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" #include @@ -60,11 +61,6 @@ #include #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * Version ::= INTEGER { v1(0) } */ @@ -168,14 +164,14 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, return( ret ); } - csr->version++; - - if( csr->version != 1 ) + if( csr->version != 0 ) { mbedtls_x509_csr_free( csr ); return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); } + csr->version++; + /* * subject Name */ @@ -265,8 +261,8 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, */ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) { - int ret; #if defined(MBEDTLS_PEM_PARSE_C) + int ret; size_t use_len; mbedtls_pem_context pem; #endif @@ -278,34 +274,34 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); #if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init( &pem ); - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( buf[buflen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else + if( buf[buflen - 1] == '\0' ) + { + mbedtls_pem_init( &pem ); ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN CERTIFICATE REQUEST-----", - "-----END CERTIFICATE REQUEST-----", - buf, NULL, 0, &use_len ); + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN NEW CERTIFICATE REQUEST-----", + "-----END NEW CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + } - if( ret == 0 ) - { - /* - * Was PEM encoded, parse the result - */ - if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); + } + + mbedtls_pem_free( &pem ); + if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); - - mbedtls_pem_free( &pem ); - return( 0 ); } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } - else #endif /* MBEDTLS_PEM_PARSE_C */ return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); } @@ -325,7 +321,7 @@ int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) ret = mbedtls_x509_csr_parse( csr, buf, n ); - mbedtls_zeroize( buf, n ); + mbedtls_platform_zeroize( buf, n ); mbedtls_free( buf ); return( ret ); @@ -407,17 +403,17 @@ void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) { name_prv = name_cur; name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); mbedtls_free( name_prv ); } if( csr->raw.p != NULL ) { - mbedtls_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_platform_zeroize( csr->raw.p, csr->raw.len ); mbedtls_free( csr->raw.p ); } - mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) ); + mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) ); } #endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/Externals/mbedtls/library/x509write_crt.c b/Externals/mbedtls/library/x509write_crt.c index d1d9a22a7e..10497e752b 100644 --- a/Externals/mbedtls/library/x509write_crt.c +++ b/Externals/mbedtls/library/x509write_crt.c @@ -37,6 +37,7 @@ #include "mbedtls/oid.h" #include "mbedtls/asn1write.h" #include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" #include @@ -44,14 +45,9 @@ #include "mbedtls/pem.h" #endif /* MBEDTLS_PEM_WRITE_C */ -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) { - memset( ctx, 0, sizeof(mbedtls_x509write_cert) ); + memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); mbedtls_mpi_init( &ctx->serial ); ctx->version = MBEDTLS_X509_CRT_VERSION_3; @@ -65,7 +61,7 @@ void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) mbedtls_asn1_free_named_data_list( &ctx->issuer ); mbedtls_asn1_free_named_data_list( &ctx->extensions ); - mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_cert) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); } void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) @@ -177,8 +173,11 @@ int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ct memset( buf, 0, sizeof(buf) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); - mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); - c = buf + sizeof(buf) - 20; + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; len = 20; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); @@ -193,14 +192,17 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert * { int ret; unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ - unsigned char *c = buf + sizeof(buf); + unsigned char *c = buf + sizeof( buf ); size_t len = 0; memset( buf, 0, sizeof(buf) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); - mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); - c = buf + sizeof(buf) - 20; + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; len = 20; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); @@ -212,30 +214,55 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert * return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), - 0, buf + sizeof(buf) - len, len ); + 0, buf + sizeof( buf ) - len, len ); } #endif /* MBEDTLS_SHA1_C */ +static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring, + size_t bit_offset ) +{ + size_t unused_bits; + + /* Count the unused bits removing trailing 0s */ + for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) + if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) + break; + + return( unused_bits ); +} + int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, unsigned int key_usage ) { unsigned char buf[4], ku; unsigned char *c; int ret; + size_t unused_bits; + const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | + MBEDTLS_X509_KU_NON_REPUDIATION | + MBEDTLS_X509_KU_KEY_ENCIPHERMENT | + MBEDTLS_X509_KU_DATA_ENCIPHERMENT | + MBEDTLS_X509_KU_KEY_AGREEMENT | + MBEDTLS_X509_KU_KEY_CERT_SIGN | + MBEDTLS_X509_KU_CRL_SIGN; - /* We currently only support 7 bits, from 0x80 to 0x02 */ - if( ( key_usage & ~0xfe ) != 0 ) + /* Check that nothing other than the allowed flags is set */ + if( ( key_usage & ~allowed_bits ) != 0 ) return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); c = buf + 4; - ku = (unsigned char) key_usage; + ku = (unsigned char)key_usage; + unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 ); + ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits ); - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) + if( ret < 0 ) return( ret ); + else if( ret < 3 || ret > 4 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), - 1, buf, 4 ); + 1, c, (size_t)ret ); if( ret != 0 ) return( ret ); @@ -247,16 +274,22 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, { unsigned char buf[4]; unsigned char *c; + size_t unused_bits; int ret; c = buf + 4; - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, + buf, + &ns_cert_type, + 8 - unused_bits ); + if( ret < 3 || ret > 4 ) return( ret ); ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), - 0, buf, 4 ); + 0, c, (size_t)ret ); if( ret != 0 ) return( ret ); @@ -264,7 +297,7 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, } static int x509_write_time( unsigned char **p, unsigned char *start, - const char *time, size_t size ) + const char *t, size_t size ) { int ret; size_t len = 0; @@ -272,10 +305,10 @@ static int x509_write_time( unsigned char **p, unsigned char *start, /* * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) */ - if( time[0] == '2' && time[1] == '0' && time [2] < '5' ) + if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) { MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) time + 2, + (const unsigned char *) t + 2, size - 2 ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); @@ -283,7 +316,7 @@ static int x509_write_time( unsigned char **p, unsigned char *start, else { MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) time, + (const unsigned char *) t, size ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); @@ -313,12 +346,18 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, c = tmp_buf + sizeof( tmp_buf ); /* Signature algorithm needed in TBS, and later for actual signature */ - pk_alg = mbedtls_pk_get_type( ctx->issuer_key ); - if( pk_alg == MBEDTLS_PK_ECKEY ) + + /* There's no direct way of extracting a signature algorithm + * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ + if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, - &sig_oid, &sig_oid_len ) ) != 0 ) + &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } @@ -326,13 +365,18 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + + /* Only for v3 */ + if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + } /* * SubjectPublicKeyInfo @@ -384,21 +428,30 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ - sub_len = 0; - MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); - len += sub_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + + /* Can be omitted for v1 */ + if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) + { + sub_len = 0; + MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + } MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_SEQUENCE ) ); /* * Make signature */ - mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, + len, hash ) ) != 0 ) + { + return( ret ); + } if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) diff --git a/Externals/mbedtls/library/x509write_csr.c b/Externals/mbedtls/library/x509write_csr.c index 8fd856b2a2..d70ba0ed92 100644 --- a/Externals/mbedtls/library/x509write_csr.c +++ b/Externals/mbedtls/library/x509write_csr.c @@ -35,6 +35,7 @@ #include "mbedtls/x509_csr.h" #include "mbedtls/oid.h" #include "mbedtls/asn1write.h" +#include "mbedtls/platform_util.h" #include #include @@ -43,14 +44,9 @@ #include "mbedtls/pem.h" #endif -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) { - memset( ctx, 0, sizeof(mbedtls_x509write_csr) ); + memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); } void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) @@ -58,7 +54,7 @@ void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) mbedtls_asn1_free_named_data_list( &ctx->subject ); mbedtls_asn1_free_named_data_list( &ctx->extensions ); - mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_csr) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); } void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) @@ -85,20 +81,39 @@ int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, 0, val, val_len ); } +static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring, + size_t bit_offset ) +{ + size_t unused_bits; + + /* Count the unused bits removing trailing 0s */ + for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) + if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) + break; + + return( unused_bits ); +} + int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) { unsigned char buf[4]; unsigned char *c; + size_t unused_bits; int ret; c = buf + 4; - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) + unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits ); + + if( ret < 0 ) return( ret ); + else if( ret < 3 || ret > 4 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), - buf, 4 ); + c, (size_t)ret ); if( ret != 0 ) return( ret ); @@ -110,16 +125,25 @@ int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, { unsigned char buf[4]; unsigned char *c; + size_t unused_bits; int ret; c = buf + 4; - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) + unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, + buf, + &ns_cert_type, + 8 - unused_bits ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 4 ) return( ret ); ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), - buf, 4 ); + c, (size_t)ret ); if( ret != 0 ) return( ret ); @@ -194,14 +218,21 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s */ mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); - pk_alg = mbedtls_pk_get_type( ctx->key ); - if( pk_alg == MBEDTLS_PK_ECKEY ) - pk_alg = MBEDTLS_PK_ECDSA; - if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, - f_rng, p_rng ) ) != 0 || - ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, - &sig_oid, &sig_oid_len ) ) != 0 ) + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } diff --git a/Externals/mbedtls/library/xtea.c b/Externals/mbedtls/library/xtea.c index fe0a3509f6..a33707bc17 100644 --- a/Externals/mbedtls/library/xtea.c +++ b/Externals/mbedtls/library/xtea.c @@ -28,6 +28,7 @@ #if defined(MBEDTLS_XTEA_C) #include "mbedtls/xtea.h" +#include "mbedtls/platform_util.h" #include @@ -42,11 +43,6 @@ #if !defined(MBEDTLS_XTEA_ALT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* * 32-bit integer manipulation macros (big endian) */ @@ -80,7 +76,7 @@ void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); } /* diff --git a/Externals/mbedtls/mbedTLS.vcxproj b/Externals/mbedtls/mbedTLS.vcxproj index b620b9e379..62d1c89265 100644 --- a/Externals/mbedtls/mbedTLS.vcxproj +++ b/Externals/mbedtls/mbedTLS.vcxproj @@ -41,6 +41,7 @@ true + @@ -49,6 +50,8 @@ + + @@ -66,6 +69,7 @@ + @@ -74,6 +78,7 @@ + true @@ -87,8 +92,11 @@ + + +