diff --git a/ChangeLog b/ChangeLog index d3636f00a..aa96b1848 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,76 @@ mbed TLS ChangeLog (Sorted per branch, date) += mbed TLS 2.1.2 released 2015-10-06 + +Security + * Added fix for CVE-2015-5291 to prevent heap corruption due to buffer + overflow of the hostname or session ticket. Found by Guido Vranken, + Intelworks. + * Fix potential double-free if mbedtls_ssl_set_hs_psk() is called more than + once in the same handhake and mbedtls_ssl_conf_psk() was used. + Found and patch provided by Guido Vranken, Intelworks. Cannot be forced + remotely. + * Fix stack buffer overflow in pkcs12 decryption (used by + mbedtls_pk_parse_key(file)() when the password is > 129 bytes. + Found by Guido Vranken, Intelworks. Not triggerable remotely. + * Fix potential buffer overflow in mbedtls_mpi_read_string(). + Found by Guido Vranken, Intelworks. Not exploitable remotely in the context + of TLS, but might be in other uses. On 32 bit machines, requires reading a + string of close to or larger than 1GB to exploit; on 64 bit machines, would + require reading a string of close to or larger than 2^62 bytes. + * Fix potential random memory allocation in mbedtls_pem_read_buffer() + on crafted PEM input data. Found and fix provided by Guido Vranken, + Intelworks. Not triggerable remotely in TLS. Triggerable remotely if you + accept PEM data from an untrusted source. + * Fix possible heap buffer overflow in base64_encoded() when the input + buffer is 512MB or larger on 32-bit platforms. Found by Guido Vranken, + Intelworks. Not trigerrable remotely in TLS. + * Fix potential double-free if mbedtls_conf_psk() is called repeatedly on + the same mbedtls_ssl_config object and memory allocation fails. Found by + Guido Vranken, Intelworks. Cannot be forced remotely. + * Fix potential heap buffer overflow in servers that perform client + authentication against a crafted CA cert. Cannot be triggered remotely + unless you allow third parties to pick trust CAs for client auth. + Found by Guido Vranken, Intelworks. + +Bugfix + * Fix compile error in net.c with musl libc. Found and patch provided by + zhasha (#278). + * Fix macroization of 'inline' keyword when building as C++. (#279) + +Changes + * Added checking of hostname length in mbedtls_ssl_set_hostname() to ensure + domain names are compliant with RFC 1035. + * Fixed paths for check_config.h in example config files. (Found by bachp) + (#291) + += mbed TLS 2.1.1 released 2015-09-17 + +Security + * Add countermeasure against Lenstra's RSA-CRT attack for PKCS#1 v1.5 + signatures. (Found by Florian Weimer, Red Hat.) + https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/ + * Fix possible client-side NULL pointer dereference (read) when the client + tries to continue the handshake after it failed (a misuse of the API). + (Found and patch provided by Fabian Foerg, Gotham Digital Science using + afl-fuzz.) + +Bugfix + * Fix warning when using a 64bit platform. (found by embedthis) (#275) + * Fix off-by-one error in parsing Supported Point Format extension that + caused some handshakes to fail. + +Changes + * Made X509 profile pointer const in mbedtls_ssl_conf_cert_profile() to allow + use of mbedtls_x509_crt_profile_next. (found by NWilson) + * When a client initiates a reconnect from the same port as a live + connection, if cookie verification is available + (MBEDTLS_SSL_DTLS_HELLO_VERIFY defined in config.h, and usable cookie + callbacks set with mbedtls_ssl_conf_dtls_cookies()), this will be + detected and mbedtls_ssl_read() will return + MBEDTLS_ERR_SSL_CLIENT_RECONNECT - it is then possible to start a new + handshake with the same context. (See RFC 6347 section 4.2.8.) + = mbed TLS 2.1.0 released 2015-09-04 Features @@ -87,7 +158,7 @@ API Changes mbedtls_gcm_init() -> mbedtls_gcm_setkey() mbedtls_hmac_drbg_init() -> mbedtls_hmac_drbg_seed(_buf)() mbedtls_ctr_drbg_init() -> mbedtls_ctr_drbg_seed() - Note that for mbetls_ssl_setup(), you need to be done setting up the + Note that for mbedtls_ssl_setup(), you need to be done setting up the ssl_config structure before calling it. * Most ssl_set_xxx() functions (all except ssl_set_bio(), ssl_set_hostname(), ssl_set_session() and ssl_set_client_transport_id(), plus diff --git a/README.md b/README.md index 79943d10a..bcc0a32c0 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx ### Yotta -[yotta](http://yottabuild.org) is a package manager and build system developped by mbed; it is the build system of mbed OS. To install it on your platform, please follow the yotta [installation instructions](http://docs.yottabuild.org/#installing). +[yotta](http://yottabuild.org) is a package manager and build system developed by mbed; it is the build system of mbed OS. To install it on your platform, please follow the yotta [installation instructions](http://docs.yottabuild.org/#installing). Once yotta is installed, you can use it to download the latest version of mbed TLS form the yotta registry with: @@ -64,7 +64,7 @@ In order to run the tests, enter: make check -The tests need Perl to be built and run. If you don't have Perl installed, you can skip buiding the tests with: +The tests need Perl to be built and run. If you don't have Perl installed, you can skip building the tests with: make no_test @@ -122,7 +122,7 @@ To list other available CMake options, use: cmake -LH -Note that, with CMake, if you want to change the compiler or its options after you already ran CMake, you need to clear its cache first, eg (using GNU find): +Note that, with CMake, if you want to change the compiler or its options after you already ran CMake, you need to clear its cache first, e.g. (using GNU find): find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} + CC=gcc CFLAGS='-fstack-protector-strong -Wa,--noexecstack' cmake . diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h index bd370919c..aee10b86f 100644 --- a/configs/config-ccm-psk-tls1_2.h +++ b/configs/config-ccm-psk-tls1_2.h @@ -80,6 +80,6 @@ */ #define MBEDTLS_SSL_MAX_CONTENT_LEN 512 -#include "check_config.h" +#include "mbedtls/check_config.h" #endif /* MBEDTLS_CONFIG_H */ diff --git a/configs/config-picocoin.h b/configs/config-picocoin.h index 426987224..26b24a9e2 100644 --- a/configs/config-picocoin.h +++ b/configs/config-picocoin.h @@ -66,6 +66,6 @@ #define MBEDTLS_SHA1_C #define MBEDTLS_SHA256_C -#include "check_config.h" +#include "mbedtls/check_config.h" #endif /* MBEDTLS_CONFIG_H */ diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h index ca7cd1d94..16320da88 100644 --- a/doxygen/input/doc_mainpage.h +++ b/doxygen/input/doc_mainpage.h @@ -21,7 +21,7 @@ */ /** - * @mainpage mbed TLS v2.1.0 source code documentation + * @mainpage mbed TLS v2.1.2 source code documentation * * This documentation describes the internal structure of mbed TLS. It was * automatically generated from specially formatted comment blocks in diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile index 6ca97c106..27b5d4b33 100644 --- a/doxygen/mbedtls.doxyfile +++ b/doxygen/mbedtls.doxyfile @@ -28,7 +28,7 @@ DOXYFILE_ENCODING = UTF-8 # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. -PROJECT_NAME = "mbed TLS v2.1.0" +PROJECT_NAME = "mbed TLS v2.1.2" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or diff --git a/include/mbedtls/base64.h b/include/mbedtls/base64.h index 28a3a4c59..352c652db 100644 --- a/include/mbedtls/base64.h +++ b/include/mbedtls/base64.h @@ -44,6 +44,9 @@ extern "C" { * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. * *olen is always updated to reflect the amount * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. * * \note Call this function with dlen = 0 to obtain the * required buffer size in *olen diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index e0eec0564..b6448ecef 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -432,6 +432,11 @@ #error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" #endif +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) #error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index 87d9c79f5..70000f5e6 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -46,7 +46,8 @@ #define MBEDTLS_CIPHER_MODE_STREAM #endif -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline) +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) #define inline __inline #endif diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index a7a27a281..3e399987c 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1153,6 +1153,22 @@ */ #define MBEDTLS_SSL_DTLS_HELLO_VERIFY +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + /** * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT * @@ -1259,6 +1275,8 @@ * If set, the X509 parser will not break-off when parsing an X509 certificate * and encountering an unknown critical extension. * + * \warning Depending on your PKI use, enabling this can be a security risk! + * * Uncomment to prevent an error. */ //#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h index a04933021..059d3c5c9 100644 --- a/include/mbedtls/ctr_drbg.h +++ b/include/mbedtls/ctr_drbg.h @@ -111,7 +111,7 @@ mbedtls_ctr_drbg_context; /** * \brief CTR_DRBG context initialization - * Makes the context ready for mbetls_ctr_drbg_seed() or + * Makes the context ready for mbedtls_ctr_drbg_seed() or * mbedtls_ctr_drbg_free(). * * \param ctx CTR_DRBG context to be initialized diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h index 4ffc6468b..e01055802 100644 --- a/include/mbedtls/hmac_drbg.h +++ b/include/mbedtls/hmac_drbg.h @@ -98,7 +98,7 @@ typedef struct /** * \brief HMAC_DRBG context initialization - * Makes the context ready for mbetls_hmac_drbg_seed(), + * Makes the context ready for mbedtls_hmac_drbg_seed(), * mbedtls_hmac_drbg_seed_buf() or * mbedtls_hmac_drbg_free(). * diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h index 1834b5992..77c2c6f68 100644 --- a/include/mbedtls/md.h +++ b/include/mbedtls/md.h @@ -27,10 +27,6 @@ #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline) -#define inline __inline -#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. */ diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index acd9068b6..e5e78fba1 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -44,6 +44,11 @@ #include "ecdsa.h" #endif +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + #define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ #define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ #define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ @@ -59,7 +64,6 @@ #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. */ - #ifdef __cplusplus extern "C" { #endif diff --git a/include/mbedtls/pkcs11.h b/include/mbedtls/pkcs11.h index aa549fd6b..2e8892813 100644 --- a/include/mbedtls/pkcs11.h +++ b/include/mbedtls/pkcs11.h @@ -37,7 +37,8 @@ #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline) +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) #define inline __inline #endif @@ -54,7 +55,7 @@ typedef struct { } mbedtls_pkcs11_context; /** - * Initialize a mbetls_pkcs11_context. + * Initialize a mbedtls_pkcs11_context. * (Just making memory references valid.) */ void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index e6b73d08e..4c061994d 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -125,6 +125,7 @@ #define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ #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. */ /* * Various constants @@ -138,6 +139,8 @@ #define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ #define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ + /* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c * NONE must be zero so that memset()ing structure to zero works */ #define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ @@ -851,7 +854,7 @@ int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); /** * \brief Initialize an SSL context - * Just makes the context ready for mbetls_ssl_setup() or + * Just makes the context ready for mbedtls_ssl_setup() or * mbedtls_ssl_free() * * \param ssl SSL context @@ -1226,6 +1229,11 @@ typedef int mbedtls_ssl_cookie_check_t( void *ctx, * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected * on the first handshake attempt when this is enabled. * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * * \param conf SSL configuration * \param f_cookie_write Cookie write callback * \param f_cookie_check Cookie check callback @@ -1438,7 +1446,7 @@ void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, * \param profile Profile to use */ void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, - mbedtls_x509_crt_profile *profile ); + const mbedtls_x509_crt_profile *profile ); /** * \brief Set the data required to verify peer certificate @@ -2169,29 +2177,35 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * * \param ssl SSL context * - * \return 0 if successful, MBEDTLS_ERR_SSL_WANT_READ, - * MBEDTLS_ERR_SSL_WANT_WRITE, or a specific SSL error code. + * \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. * - * \note If this function returns non-zero, then the ssl context + * \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. - * If DTLS is in use, then you may choose to handle + * + * \note If DTLS is in use, then you may choose to handle * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging - * purposes, but you still need to reset/free the context. + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. */ 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 + * \note The state of the context (ssl->state) will be at * the following state after execution of this function. * Do not call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. * * \param ssl SSL context * - * \return 0 if successful, MBEDTLS_ERR_SSL_WANT_READ, - * MBEDTLS_ERR_SSL_WANT_WRITE, or a specific SSL error code. + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * a specific SSL error code. */ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); @@ -2218,7 +2232,23 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * * \return the number of bytes read, or * 0 for EOF, or - * a negative error code. + * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or + * another negative error code. + * + * \note When this function return 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 + * 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! */ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); diff --git a/include/mbedtls/ssl_cache.h b/include/mbedtls/ssl_cache.h index 53f043e97..1155924a9 100644 --- a/include/mbedtls/ssl_cache.h +++ b/include/mbedtls/ssl_cache.h @@ -121,7 +121,7 @@ void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeou #endif /* MBEDTLS_HAVE_TIME */ /** - * \brief Set the cache timeout + * \brief Set the maximum number of cache entries * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) * * \param cache SSL cache context diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 68e45a081..ecfc971dd 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -45,7 +45,8 @@ #include "ecjpake.h" #endif -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline) +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) #define inline __inline #endif diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h index cc8754c80..ae7a713e7 100644 --- a/include/mbedtls/timing.h +++ b/include/mbedtls/timing.h @@ -92,7 +92,7 @@ void mbedtls_set_alarm( int seconds ); * (See \c mbedtls_timing_get_delay().) * * \param data Pointer to timing data - * Must point to a valid \c mbetls_timing_delay_context struct. + * Must point to a valid \c mbedtls_timing_delay_context struct. * \param int_ms First (intermediate) delay in milliseconds. * \param fin_ms Second (final) delay in milliseconds. * Pass 0 to cancel the current delay. @@ -104,7 +104,7 @@ void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); * (Memory helper: number of delays passed.) * * \param data Pointer to timing data - * Must point to a valid \c mbetls_timing_delay_context struct. + * Must point to a valid \c mbedtls_timing_delay_context struct. * * \return -1 if cancelled (fin_ms = 0) * 0 if none of the delays are passed, diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h index da76e76cb..8bc2708e9 100644 --- a/include/mbedtls/version.h +++ b/include/mbedtls/version.h @@ -39,16 +39,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 1 -#define MBEDTLS_VERSION_PATCH 0 +#define MBEDTLS_VERSION_PATCH 2 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02010000 -#define MBEDTLS_VERSION_STRING "2.1.0" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.1.0" +#define MBEDTLS_VERSION_NUMBER 0x02010200 +#define MBEDTLS_VERSION_STRING "2.1.2" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.1.2" #if defined(MBEDTLS_VERSION_C) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index d6c551a74..58a97e8e0 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -139,15 +139,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY) if(USE_SHARED_MBEDTLS_LIBRARY) add_library(mbedcrypto SHARED ${src_crypto}) - set_target_properties(mbedcrypto PROPERTIES VERSION 2.1.0 SOVERSION 0) + set_target_properties(mbedcrypto PROPERTIES VERSION 2.1.2 SOVERSION 0) target_link_libraries(mbedcrypto ${libs}) add_library(mbedx509 SHARED ${src_x509}) - set_target_properties(mbedx509 PROPERTIES VERSION 2.1.0 SOVERSION 0) + set_target_properties(mbedx509 PROPERTIES VERSION 2.1.2 SOVERSION 0) target_link_libraries(mbedx509 ${libs} mbedcrypto) add_library(mbedtls SHARED ${src_tls}) - set_target_properties(mbedtls PROPERTIES VERSION 2.1.0 SOVERSION 10) + set_target_properties(mbedtls PROPERTIES VERSION 2.1.2 SOVERSION 10) target_link_libraries(mbedtls ${libs} mbedx509) install(TARGETS mbedtls mbedx509 mbedcrypto diff --git a/library/base64.c b/library/base64.c index 16c254da9..3432e5fcd 100644 --- a/library/base64.c +++ b/library/base64.c @@ -69,6 +69,8 @@ static const unsigned char base64_dec_map[128] = 49, 50, 51, 127, 127, 127, 127, 127 }; +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + /* * Encode a buffer into base64 format */ @@ -85,15 +87,16 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, return( 0 ); } - n = ( slen << 3 ) / 6; + n = slen / 3 + ( slen % 3 != 0 ); - switch( ( slen << 3 ) - ( n * 6 ) ) + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) { - case 2: n += 3; break; - case 4: n += 2; break; - default: break; + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); } + n *= 4; + if( dlen < n + 1 ) { *olen = n + 1; @@ -184,7 +187,10 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, } if( n == 0 ) + { + *olen = 0; return( 0 ); + } n = ( ( n * 6 ) + 7 ) >> 3; n -= j; diff --git a/library/bignum.c b/library/bignum.c index 15cbf73fb..58a4cd2de 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -22,7 +22,7 @@ * This MPI implementation is based on: * * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf - * http://www.stillhq.com/extracted/gnupg-api/mbedtls_mpi/ + * http://www.stillhq.com/extracted/gnupg-api/mpi/ * http://math.libtomcrypt.com/files/tommath.pdf */ @@ -58,11 +58,14 @@ static void mbedtls_zeroize( void *v, size_t n ) { #define biL (ciL << 3) /* bits in limb */ #define biH (ciL << 2) /* half limb size */ +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + /* * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows */ -#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) -#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) /* * Initialize one MPI @@ -409,6 +412,9 @@ int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) if( radix == 16 ) { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + n = BITS_TO_LIMBS( slen << 2 ); MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); diff --git a/library/debug.c b/library/debug.c index 070f63a72..4752ab1a3 100644 --- a/library/debug.c +++ b/library/debug.c @@ -42,7 +42,8 @@ #define mbedtls_snprintf snprintf #endif -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline) +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) #define inline __inline #endif diff --git a/library/ecp.c b/library/ecp.c index 89a5612b9..4abc87c61 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -62,7 +62,8 @@ #define mbedtls_free free #endif -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline) +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) #define inline __inline #endif diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 68323c582..9a6e8eb18 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -31,7 +31,8 @@ #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && !defined(inline) +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) #define inline __inline #endif diff --git a/library/error.c b/library/error.c index a7de11007..a1cf83aed 100644 --- a/library/error.c +++ b/library/error.c @@ -428,6 +428,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) + mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) diff --git a/library/net.c b/library/net.c index b892df91b..a77268c55 100644 --- a/library/net.c +++ b/library/net.c @@ -292,7 +292,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, struct sockaddr_storage client_addr; #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ - defined(_SOCKLEN_T_DECLARED) + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) socklen_t n = (socklen_t) sizeof( client_addr ); socklen_t type_len = (socklen_t) sizeof( type ); #else @@ -319,7 +319,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, /* UDP: wait for a message, but keep it in the queue */ char buf[1] = { 0 }; - ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, (struct sockaddr *) &client_addr, &n ); #if defined(_WIN32) diff --git a/library/pem.c b/library/pem.c index 541e870c3..1ee3966e1 100644 --- a/library/pem.c +++ b/library/pem.c @@ -316,6 +316,9 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ } + if( s1 == s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) diff --git a/library/pkcs12.c b/library/pkcs12.c index f1777eb70..7023b9dbc 100644 --- a/library/pkcs12.c +++ b/library/pkcs12.c @@ -86,6 +86,8 @@ static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, return( 0 ); } +#define PKCS12_MAX_PWDLEN 128 + static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, unsigned char *key, size_t keylen, @@ -94,7 +96,10 @@ static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_ty int ret, iterations; mbedtls_asn1_buf salt; size_t i; - unsigned char unipwd[258]; + unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; + + if( pwdlen > PKCS12_MAX_PWDLEN ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); memset( &unipwd, 0, sizeof(unipwd) ); @@ -125,6 +130,8 @@ static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_ty return( 0 ); } +#undef PKCS12_MAX_PWDLEN + int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, diff --git a/library/rsa.c b/library/rsa.c index f4ab6b2a6..3883d0921 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -51,6 +51,8 @@ #else #include #define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free #endif /* @@ -1005,6 +1007,11 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, 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; if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); @@ -1067,9 +1074,39 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, memcpy( p, hash, hashlen ); } - return( ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, sig, sig ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); + if( mode == MBEDTLS_RSA_PUBLIC ) + return( mbedtls_rsa_public( ctx, sig, sig ) ); + + /* + * 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 ); + verif = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL || verif == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + 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 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + return( ret ); } #endif /* MBEDTLS_PKCS1_V15 */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 5890227b1..5d9af17e4 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -60,6 +60,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; size_t hostname_len; *olen = 0; @@ -72,6 +73,12 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, hostname_len = strlen( ssl->hostname ); + if( end < p || (size_t)( end - p ) < hostname_len + 9 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + /* * struct { * NameType name_type; @@ -115,6 +122,7 @@ 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; *olen = 0; @@ -123,6 +131,12 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); + if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + /* * Secure renegotiation */ @@ -149,6 +163,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; size_t sig_alg_len = 0; const int *md; #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) @@ -162,9 +177,27 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + } + + if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + /* * Prepare signature_algorithms extension (TLS 1.2) */ + sig_alg_len = 0; + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) { #if defined(MBEDTLS_ECDSA_C) @@ -215,6 +248,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; unsigned char *elliptic_curve_list = p + 6; size_t elliptic_curve_len = 0; const mbedtls_ecp_curve_info *info; @@ -228,6 +262,25 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); +#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 + elliptic_curve_len += 2; + } + + if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + elliptic_curve_len = 0; + #if defined(MBEDTLS_ECP_C) for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) { @@ -261,13 +314,19 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, size_t *olen ) { unsigned char *p = buf; - ((void) ssl); + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; *olen = 0; MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); + if( end < p || (size_t)( end - p ) < 6 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); *p++ = 0x00; @@ -365,14 +424,22 @@ 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; + + *olen = 0; if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) { - *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); + if( end < p || (size_t)( end - p ) < 5 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); @@ -390,15 +457,23 @@ 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; + + *olen = 0; if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) { - *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); @@ -414,17 +489,25 @@ 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; + + *olen = 0; if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { - *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac " "extension" ) ); + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); @@ -440,17 +523,25 @@ 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; + + *olen = 0; if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { - *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " "extension" ) ); + if( end < p || (size_t)( end - p ) < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); @@ -466,16 +557,24 @@ 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; size_t tlen = ssl->session_negotiate->ticket_len; + *olen = 0; + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) { - *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); + if( end < p || (size_t)( end - p ) < 4 + tlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); @@ -484,8 +583,7 @@ static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, *olen = 4; - if( ssl->session_negotiate->ticket == NULL || - ssl->session_negotiate->ticket_len == 0 ) + if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) { return; } @@ -503,16 +601,28 @@ 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; + size_t alpnlen = 0; const char **cur; + *olen = 0; + if( ssl->conf->alpn_list == NULL ) { - *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1; + + if( end < p || (size_t)( end - p ) < 6 + alpnlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); @@ -891,13 +1001,13 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ext_len += olen; #endif -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif -#if defined(MBEDTLS_SSL_ALPN) - ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); ext_len += olen; #endif @@ -1917,6 +2027,12 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, ssl->handshake->pmslen = 48; + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + /* * Now write it out, encrypted */ @@ -2019,6 +2135,12 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) int ret; const mbedtls_ecp_keypair *peer_key; + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, MBEDTLS_PK_ECKEY ) ) { @@ -2341,6 +2463,12 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + /* * Verify signature */ diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 716cb20fa..9afd39989 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -2460,6 +2460,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) 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 mbedtls_x509_crt *crt; int authmode; @@ -2581,10 +2582,14 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) total_dn_size = 0; while( crt != NULL && crt->version != 0 ) { - if( p - buf > 4096 ) - break; - dn_size = crt->subject_raw.len; + + if( end < p || (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 ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 212cde93f..47659b6c1 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3260,6 +3260,196 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* Forward declaration */ +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + if( f_cookie_write == NULL || f_cookie_check == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); + obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); + obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); + + obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); + obuf[12] = (unsigned char)( ( *olen - 13 ) ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * mbedtls_ssl_read_record() will ignore the record if anything else than + * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function + * cannot not return 0. + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret; + size_t len; + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + 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 ); + + 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. + * 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 ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); + } + + if( ret == 0 ) + { + /* Got a valid cookie, partially reset context */ + if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + /* * ContentType type; * ProtocolVersion version; @@ -3351,13 +3541,36 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) if( rec_epoch != ssl->in_epoch ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " - "expected %d, received %d", - ssl->in_epoch, rec_epoch ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + "expected %d, received %d", + ssl->in_epoch, rec_epoch ) ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + rec_epoch == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + /* Replay detection only works for the current epoch */ + if( rec_epoch == ssl->in_epoch && + mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); @@ -3538,7 +3751,8 @@ read_record_header: if( ( ret = ssl_parse_record_header( ssl ) ) != 0 ) { #if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) { /* Ignore bad record and get next one; drop the whole datagram * since current header cannot be trusted to find the next record @@ -5144,8 +5358,11 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, /* * Reset an initialized and used SSL context for re-use while retaining * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) */ -int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) { int ret; @@ -5169,7 +5386,8 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) ssl->in_msg = ssl->in_buf + 13; ssl->in_msgtype = 0; ssl->in_msglen = 0; - ssl->in_left = 0; + if( partial == 0 ) + ssl->in_left = 0; #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->next_record_offset = 0; ssl->in_epoch = 0; @@ -5195,7 +5413,8 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) ssl->transform_out = NULL; memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); - memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); + if( partial == 0 ) + memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) if( mbedtls_ssl_hw_record_reset != NULL ) @@ -5228,9 +5447,12 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - mbedtls_free( ssl->cli_id ); - ssl->cli_id = NULL; - ssl->cli_id_len = 0; + if( partial == 0 ) + { + mbedtls_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } #endif if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) @@ -5239,6 +5461,15 @@ int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) return( 0 ); } +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + return( ssl_session_reset_int( ssl, 0 ) ); +} + /* * SSL set accessors */ @@ -5393,7 +5624,7 @@ void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, #if defined(MBEDTLS_X509_CRT_PARSE_C) void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, - mbedtls_x509_crt_profile *profile ) + const mbedtls_x509_crt_profile *profile ) { conf->cert_profile = profile; } @@ -5523,7 +5754,9 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) { mbedtls_free( conf->psk ); + mbedtls_free( conf->psk_identity ); conf->psk = NULL; + conf->psk_identity = NULL; return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } @@ -5546,7 +5779,7 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); if( ssl->handshake->psk != NULL ) - mbedtls_free( ssl->conf->psk ); + mbedtls_free( ssl->handshake->psk ); if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) { @@ -5649,6 +5882,9 @@ int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) 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 ) @@ -6827,7 +7063,7 @@ static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { #endif /* - * Load default in mbetls_ssl_config + * Load default in mbedtls_ssl_config */ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, int endpoint, int transport, int preset ) diff --git a/library/version_features.c b/library/version_features.c index ca040ab76..1575e093e 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -372,6 +372,9 @@ static const char *features[] = { #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) "MBEDTLS_SSL_DTLS_HELLO_VERIFY", #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c index f60cad762..63a3aeb98 100644 --- a/programs/pkey/gen_key.c +++ b/programs/pkey/gen_key.c @@ -209,7 +209,7 @@ int main( int argc, char *argv[] ) ret = 1; mbedtls_printf( USAGE ); #if defined(MBEDTLS_ECP_C) - mbedtls_printf( " availabled ec_curve values:\n" ); + mbedtls_printf( " available ec_curve values:\n" ); curve_info = mbedtls_ecp_curve_list(); mbedtls_printf( " %s (default)\n", curve_info->name ); while( ( ++curve_info )->name != NULL ) diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c index 606fc93d7..322e8aff0 100644 --- a/programs/pkey/pk_sign.c +++ b/programs/pkey/pk_sign.c @@ -40,7 +40,7 @@ int main( void ) { mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " - "MBEDTLS_SHA256_C and/or MBEDLTS_MD_C and/or " + "MBEDTLS_SHA256_C and/or MBEDTLS_MD_C and/or " "MBEDTLS_PK_PARSE_C and/or MBEDTLS_FS_IO and/or " "MBEDTLS_CTR_DRBG_C not defined.\n"); return( 0 ); diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c index 469ad9f5d..e897c6519 100644 --- a/programs/pkey/rsa_sign.c +++ b/programs/pkey/rsa_sign.c @@ -40,7 +40,7 @@ int main( void ) { mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " - "MBEDLTS_MD_C and/or " + "MBEDTLS_MD_C and/or " "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n"); return( 0 ); } diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c index 9d48a18ee..ade36dc83 100644 --- a/programs/pkey/rsa_verify.c +++ b/programs/pkey/rsa_verify.c @@ -39,7 +39,7 @@ int main( void ) { mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " - "MBEDLTS_MD_C and/or " + "MBEDTLS_MD_C and/or " "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO not defined.\n"); return( 0 ); } diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 53ec635af..559e5028d 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -91,6 +91,7 @@ int main( void ) #define DFL_DHMLEN -1 #define DFL_RECONNECT 0 #define DFL_RECO_DELAY 0 +#define DFL_RECONNECT_HARD 0 #define DFL_TICKETS MBEDTLS_SSL_SESSION_TICKETS_ENABLED #define DFL_ALPN_STRING NULL #define DFL_TRANSPORT MBEDTLS_SSL_TRANSPORT_STREAM @@ -230,7 +231,7 @@ int main( void ) " debug_level=%%d default: 0 (disabled)\n" \ " nbio=%%d default: 0 (blocking I/O)\n" \ " options: 1 (non-blocking), 2 (added delays)\n" \ - " read_timeout=%%d default: 0 (no timeout)\n" \ + " read_timeout=%%d default: 0 ms (no timeout)\n" \ " max_resend=%%d default: 0 (no resend on timeout)\n" \ "\n" \ USAGE_DTLS \ @@ -247,6 +248,7 @@ int main( void ) " exchanges=%%d default: 1\n" \ " reconnect=%%d default: 0 (disabled)\n" \ " reco_delay=%%d default: 0 seconds\n" \ + " reconnect_hard=%%d default: 0 (disabled)\n" \ USAGE_TICKETS \ USAGE_MAX_FRAG_LEN \ USAGE_TRUNC_HMAC \ @@ -303,6 +305,7 @@ struct options int dhmlen; /* minimum DHM params len in bits */ int reconnect; /* attempt to resume session */ int reco_delay; /* delay in seconds before resuming session */ + int reconnect_hard; /* unexpectedly reconnect from the same port */ int tickets; /* enable / disable session tickets */ const char *alpn_string; /* ALPN supported protocols */ int transport; /* TLS or DTLS? */ @@ -492,6 +495,7 @@ int main( int argc, char *argv[] ) opt.dhmlen = DFL_DHMLEN; opt.reconnect = DFL_RECONNECT; opt.reco_delay = DFL_RECO_DELAY; + opt.reconnect_hard = DFL_RECONNECT_HARD; opt.tickets = DFL_TICKETS; opt.alpn_string = DFL_ALPN_STRING; opt.transport = DFL_TRANSPORT; @@ -616,6 +620,12 @@ int main( int argc, char *argv[] ) if( opt.reco_delay < 0 ) goto usage; } + else if( strcmp( p, "reconnect_hard" ) == 0 ) + { + opt.reconnect_hard = atoi( q ); + if( opt.reconnect_hard < 0 || opt.reconnect_hard > 1 ) + goto usage; + } else if( strcmp( p, "tickets" ) == 0 ) { opt.tickets = atoi( q ); @@ -1505,7 +1515,38 @@ send_request: } /* - * 7b. Continue doing data exchanges? + * 7b. Simulate hard reset and reconnect from same port? + */ + if( opt.reconnect_hard != 0 ) + { + opt.reconnect_hard = 0; + + mbedtls_printf( " . Restarting connection from same port..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret ); + goto exit; + } + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); + goto exit; + } + } + + mbedtls_printf( " ok\n" ); + + goto send_request; + } + + /* + * 7c. Continue doing data exchanges? */ if( --opt.exchanges > 0 ) goto send_request; @@ -1515,6 +1556,7 @@ send_request: */ close_notify: mbedtls_printf( " . Closing the connection..." ); + fflush( stdout ); /* No error checking, the connection might be closed already */ do ret = mbedtls_ssl_close_notify( &ssl ); @@ -1539,7 +1581,6 @@ reconnect: #endif mbedtls_printf( " . Reconnecting with saved session..." ); - fflush( stdout ); if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) { diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 3f88452b6..b586a7008 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -309,7 +309,7 @@ int main( void ) " debug_level=%%d default: 0 (disabled)\n" \ " nbio=%%d default: 0 (blocking I/O)\n" \ " options: 1 (non-blocking), 2 (added delays)\n" \ - " read_timeout=%%d default: 0 (no timeout)\n" \ + " read_timeout=%%d default: 0 ms (no timeout)\n" \ "\n" \ USAGE_DTLS \ USAGE_COOKIES \ @@ -1851,6 +1851,12 @@ reset: } #endif + if( ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) + { + mbedtls_printf( " ! Client initiated reconnection from same port\n" ); + goto handshake; + } + #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { @@ -1929,6 +1935,7 @@ reset: /* * 4. Handshake */ +handshake: mbedtls_printf( " . Performing the SSL/TLS handshake..." ); fflush( stdout ); diff --git a/scripts/memory.sh b/scripts/memory.sh index 0738e7de2..3dad2899c 100755 --- a/scripts/memory.sh +++ b/scripts/memory.sh @@ -52,6 +52,8 @@ do_config() scripts/config.pl unset $FLAG done + grep -F SSL_MAX_CONTENT_LEN $CONFIG_H || echo 'SSL_MAX_CONTENT_LEN=16384' + printf " Executable size... " make clean diff --git a/tests/scripts/yotta-build.sh b/tests/scripts/yotta-build.sh index 59cedf42b..2648d3e29 100755 --- a/tests/scripts/yotta-build.sh +++ b/tests/scripts/yotta-build.sh @@ -6,7 +6,7 @@ set -eu yotta/create-module.sh cd yotta/module -# yt update # needs network +yt update || true # needs network yotta_build() { diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index ff2ca366f..04f4a887a 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -2951,6 +2951,40 @@ run_test "DTLS cookie: enabled, nbio" \ -s "hello verification requested" \ -S "SSL - The requested feature is not available" +# Tests for client reconnecting from the same port with DTLS + +not_with_valgrind # spurious resend +run_test "DTLS client reconnect from same port: reference" \ + "$P_SRV dtls=1 exchanges=2 read_timeout=1000" \ + "$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000" \ + 0 \ + -C "resend" \ + -S "The operation timed out" \ + -S "Client initiated reconnection from same port" + +not_with_valgrind # spurious resend +run_test "DTLS client reconnect from same port: reconnect" \ + "$P_SRV dtls=1 exchanges=2 read_timeout=1000" \ + "$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000 reconnect_hard=1" \ + 0 \ + -C "resend" \ + -S "The operation timed out" \ + -s "Client initiated reconnection from same port" + +run_test "DTLS client reconnect from same port: reconnect, nbio" \ + "$P_SRV dtls=1 exchanges=2 read_timeout=1000 nbio=2" \ + "$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-1000 reconnect_hard=1" \ + 0 \ + -S "The operation timed out" \ + -s "Client initiated reconnection from same port" + +run_test "DTLS client reconnect from same port: no cookies" \ + "$P_SRV dtls=1 exchanges=2 read_timeout=1000 cookies=0" \ + "$P_CLI dtls=1 exchanges=2 debug_level=2 hs_timeout=500-8000 reconnect_hard=1" \ + 0 \ + -s "The operation timed out" \ + -S "Client initiated reconnection from same port" + # Tests for various cases of client authentication with DTLS # (focused on handshake flows and message parsing) diff --git a/tests/suites/test_suite_base64.data b/tests/suites/test_suite_base64.data index 3b66da165..da99ffa87 100644 --- a/tests/suites/test_suite_base64.data +++ b/tests/suites/test_suite_base64.data @@ -1,23 +1,41 @@ -Test case mbedtls_base64_encode #1 -mbedtls_base64_encode:"":"":1000:0 +Test case mbedtls_base64_encode #1 buffer just right +mbedtls_base64_encode:"":"":0:0 -Test case mbedtls_base64_encode #2 -mbedtls_base64_encode:"f":"Zg==":1000:0 +Test case mbedtls_base64_encode #2 buffer just right +mbedtls_base64_encode:"f":"Zg==":5:0 -Test case mbedtls_base64_encode #3 -mbedtls_base64_encode:"fo":"Zm8=":1000:0 +Test case mbedtls_base64_encode #2 buffer too small +mbedtls_base64_encode:"f":"Zg==":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -Test case mbedtls_base64_encode #4 -mbedtls_base64_encode:"foo":"Zm9v":1000:0 +Test case mbedtls_base64_encode #3 buffer just right +mbedtls_base64_encode:"fo":"Zm8=":5:0 -Test case mbedtls_base64_encode #5 -mbedtls_base64_encode:"foob":"Zm9vYg==":1000:0 +Test case mbedtls_base64_encode #3 buffer too small +mbedtls_base64_encode:"fo":"Zm8=":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -Test case mbedtls_base64_encode #6 -mbedtls_base64_encode:"fooba":"Zm9vYmE=":1000:0 +Test case mbedtls_base64_encode #4 buffer just right +mbedtls_base64_encode:"foo":"Zm9v":5:0 -Test case mbedtls_base64_encode #7 -mbedtls_base64_encode:"foobar":"Zm9vYmFy":1000:0 +Test case mbedtls_base64_encode #4 buffer too small +mbedtls_base64_encode:"foo":"Zm9v":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL + +Test case mbedtls_base64_encode #5 buffer just right +mbedtls_base64_encode:"foob":"Zm9vYg==":9:0 + +Test case mbedtls_base64_encode #5 buffer too small +mbedtls_base64_encode:"foob":"Zm9vYg==":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL + +Test case mbedtls_base64_encode #6 buffer just right +mbedtls_base64_encode:"fooba":"Zm9vYmE=":9:0 + +Test case mbedtls_base64_encode #6 buffer too small +mbedtls_base64_encode:"fooba":"Zm9vYmE=":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL + +Test case mbedtls_base64_encode #7 buffer just right +mbedtls_base64_encode:"foobar":"Zm9vYmFy":9:0 + +Test case mbedtls_base64_encode #7 buffer too small +mbedtls_base64_encode:"foobar":"Zm9vYmFy":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL Test case mbedtls_base64_decode #1 mbedtls_base64_decode:"":"":0 @@ -40,12 +58,6 @@ mbedtls_base64_decode:"Zm9vYmE=":"fooba":0 Test case mbedtls_base64_decode #7 mbedtls_base64_decode:"Zm9vYmFy":"foobar":0 -Base64 encode (buffer size just right) -mbedtls_base64_encode:"foobar":"Zm9vYmFy":9:0 - -Base64 encode (buffer size too small) -mbedtls_base64_encode:"foobar":"":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL - Base64 decode (Illegal character) mbedtls_base64_decode:"zm#=":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data index 29ea2d22d..a2955c662 100644 --- a/tests/suites/test_suite_version.data +++ b/tests/suites/test_suite_version.data @@ -1,8 +1,8 @@ Check compiletime library version -check_compiletime_version:"2.1.0" +check_compiletime_version:"2.1.2" Check runtime library version -check_runtime_version:"2.1.0" +check_runtime_version:"2.1.2" Check for MBEDTLS_VERSION_C check_feature:"MBEDTLS_VERSION_C":0 diff --git a/yotta/data/example-authcrypt/main.cpp b/yotta/data/example-authcrypt/main.cpp index 2f49aa91c..257a1adf1 100644 --- a/yotta/data/example-authcrypt/main.cpp +++ b/yotta/data/example-authcrypt/main.cpp @@ -187,7 +187,7 @@ static void run() { } void app_start(int, char*[]) { - minar::Scheduler::postCallback(FunctionPointer0(run).bind()); + minar::Scheduler::postCallback(mbed::util::FunctionPointer0(run).bind()); } #else diff --git a/yotta/data/example-benchmark/main.cpp b/yotta/data/example-benchmark/main.cpp index 6ac2a29e8..1a6c7ae7a 100644 --- a/yotta/data/example-benchmark/main.cpp +++ b/yotta/data/example-benchmark/main.cpp @@ -947,7 +947,7 @@ static void run() { } void app_start(int, char*[]) { - minar::Scheduler::postCallback(FunctionPointer0(run).bind()); + minar::Scheduler::postCallback(mbed::util::FunctionPointer0(run).bind()); } #endif /* TARGET_LIKE_MBED */ diff --git a/yotta/data/example-hashing/main.cpp b/yotta/data/example-hashing/main.cpp index 4ef3665fe..7603cbee6 100644 --- a/yotta/data/example-hashing/main.cpp +++ b/yotta/data/example-hashing/main.cpp @@ -167,7 +167,7 @@ static void run() { } void app_start(int, char*[]) { - minar::Scheduler::postCallback(FunctionPointer0(run).bind()); + minar::Scheduler::postCallback(mbed::util::FunctionPointer0(run).bind()); } #else diff --git a/yotta/data/example-selftest/main.cpp b/yotta/data/example-selftest/main.cpp index 22fd4661f..046a54850 100644 --- a/yotta/data/example-selftest/main.cpp +++ b/yotta/data/example-selftest/main.cpp @@ -258,7 +258,7 @@ static void run() { } void app_start(int, char*[]) { - minar::Scheduler::postCallback(FunctionPointer0(run).bind()); + minar::Scheduler::postCallback(mbed::util::FunctionPointer0(run).bind()); } #else diff --git a/yotta/data/example-tls-client/main.cpp b/yotta/data/example-tls-client/main.cpp index 684f1c16e..907cfb6d4 100644 --- a/yotta/data/example-tls-client/main.cpp +++ b/yotta/data/example-tls-client/main.cpp @@ -513,7 +513,7 @@ void app_start(int, char*[]) { printf("Client IP Address is %s\r\n", eth.getIPAddress()); - mbed::FunctionPointer1 fp(hello, &HelloHTTPS::startTest); + mbed::util::FunctionPointer1 fp(hello, &HelloHTTPS::startTest); minar::Scheduler::postCallback(fp.bind(HTTPS_PATH)); } diff --git a/yotta/data/module.json b/yotta/data/module.json index 5b57cc209..848ad03f9 100644 --- a/yotta/data/module.json +++ b/yotta/data/module.json @@ -1,6 +1,6 @@ { "name": "mbedtls", - "version": "2.1.0", + "version": "2.1.4", "description": "The mbed TLS crypto/SSL/TLS library", "licenses": [ { @@ -10,9 +10,9 @@ ], "dependencies": {}, "targetDependencies": { - "mbed": { "cmsis-core": "~0.2.3" } + "mbed": { "cmsis-core": "^1.0.0" } }, "testTargetDependencies": { - "mbed": { "sockets": "~0.3.0" } + "mbed": { "sockets": "^1.0.0" } } }