Merge branch 'development' into iotssl-461-ecjpake-finalization
* development: (73 commits)
Bump yotta dependencies version
Fix typo in documentation
Corrected misleading fn description in ssl_cache.h
Corrected URL/reference to MPI library
Fix yotta dependencies
Fix minor spelling mistake in programs/pkey/gen_key.c
Bump version to 2.1.2
Fix CVE number in ChangeLog
Add 'inline' workaround where needed
Fix references to non-standard SIZE_T_MAX
Fix yotta version dependencies again
Upgrade yotta dependency versions
Fix compile error in net.c with musl libc
Add missing warning in doc
Remove inline workaround when not useful
Fix macroization of inline in C++
Changed attribution for Guido Vranken
Merge of IOTSSL-476 - Random malloc in pem_read()
Fix for IOTSSL-473 Double free error
Fix potential overflow in CertificateRequest
...
Conflicts:
include/mbedtls/ssl_internal.h
library/ssl_cli.c
diff --git a/ChangeLog b/ChangeLog
index d3636f0..aa96b18 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 @@
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 79943d1..bcc0a32 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@
### 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 @@
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 @@
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 bd37091..aee10b8 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 4269872..26b24a9 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 ca7cd1d..16320da 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 6ca97c1..27b5d4b 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -28,7 +28,7 @@
# 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 28a3a4c..352c652 100644
--- a/include/mbedtls/base64.h
+++ b/include/mbedtls/base64.h
@@ -44,6 +44,9 @@
* \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 e0eec05..b6448ec 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 87d9c79..70000f5 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 a7a27a2..3e39998 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1154,6 +1154,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
*
* Enable support for a limit of records with bad MAC.
@@ -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 a049330..059d3c5 100644
--- a/include/mbedtls/ctr_drbg.h
+++ b/include/mbedtls/ctr_drbg.h
@@ -111,7 +111,7 @@
/**
* \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 4ffc646..e010558 100644
--- a/include/mbedtls/hmac_drbg.h
+++ b/include/mbedtls/hmac_drbg.h
@@ -98,7 +98,7 @@
/**
* \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 1834b59..77c2c6f 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -27,10 +27,6 @@
#include <stddef.h>
-#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 acd9068..e5e78fb 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 aa549fd..2e88928 100644
--- a/include/mbedtls/pkcs11.h
+++ b/include/mbedtls/pkcs11.h
@@ -37,7 +37,8 @@
#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
-#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 @@
} 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 e6b73d0..4c06199 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 @@
/**
* \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 @@
* 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 @@
* \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 @@
*
* \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 @@
*
* \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 53f043e..1155924 100644
--- a/include/mbedtls/ssl_cache.h
+++ b/include/mbedtls/ssl_cache.h
@@ -121,7 +121,7 @@
#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 68e45a0..ecfc971 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 cc8754c..ae7a713 100644
--- a/include/mbedtls/timing.h
+++ b/include/mbedtls/timing.h
@@ -92,7 +92,7 @@
* (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 @@
* (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 da76e76..8bc2708 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 d6c551a..58a97e8 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -139,15 +139,15 @@
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 16c254d..3432e5f 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -69,6 +69,8 @@
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 @@
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 @@
}
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 15cbf73..58a4cd2 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 @@
#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 @@
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 070f63a..4752ab1 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 89a5612..4abc87c 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 68323c5..9a6e8eb 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -31,7 +31,8 @@
#include <string.h>
-#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 a7de110..a1cf83a 100644
--- a/library/error.c
+++ b/library/error.c
@@ -428,6 +428,8 @@
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 b892df9..a77268c 100644
--- a/library/net.c
+++ b/library/net.c
@@ -292,7 +292,7 @@
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 @@
/* 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 541e870..1ee3966 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -316,6 +316,9 @@
( 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 f1777eb..7023b9d 100644
--- a/library/pkcs12.c
+++ b/library/pkcs12.c
@@ -86,6 +86,8 @@
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 @@
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 @@
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 f4ab6b2a..3883d09 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -51,6 +51,8 @@
#else
#include <stdio.h>
#define mbedtls_printf printf
+#define mbedtls_calloc calloc
+#define mbedtls_free free
#endif
/*
@@ -1005,6 +1007,11 @@
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 @@
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 5890227..5d9af17 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -60,6 +60,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
@@ -236,6 +270,25 @@
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++ )
+ {
+ 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_list[elliptic_curve_len++] = info->tls_id >> 8;
elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF;
@@ -261,13 +314,19 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
*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 @@
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 @@
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 @@
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 @@
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 @@
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 716cb20..9afd399 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -2460,6 +2460,7 @@
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 @@
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 212cde9..47659b6 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -3260,6 +3260,196 @@
}
#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 @@
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 @@
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 @@
/*
* 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 @@
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 @@
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 @@
#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 )
@@ -5240,6 +5462,15 @@
}
/*
+ * 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
*/
void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint )
@@ -5393,7 +5624,7 @@
#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 @@
( 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 @@
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 @@
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 @@
#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 ca040ab..1575e09 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -372,6 +372,9 @@
#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 f60cad7..63a3aeb 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -209,7 +209,7 @@
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 606fc93..322e8af 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 469ad9f..e897c65 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 9d48a18..ade36dc 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 53ec635..559e502 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -91,6 +91,7 @@
#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 @@
" 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 @@
" 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 @@
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 @@
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 @@
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 @@
}
/*
- * 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 @@
*/
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 @@
#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 3f88452..b586a70 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -309,7 +309,7 @@
" 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 @@
}
#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 @@
/*
* 4. Handshake
*/
+handshake:
mbedtls_printf( " . Performing the SSL/TLS handshake..." );
fflush( stdout );
diff --git a/scripts/memory.sh b/scripts/memory.sh
index 0738e7d..3dad289 100755
--- a/scripts/memory.sh
+++ b/scripts/memory.sh
@@ -52,6 +52,8 @@
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 59cedf4..2648d3e 100755
--- a/tests/scripts/yotta-build.sh
+++ b/tests/scripts/yotta-build.sh
@@ -6,7 +6,7 @@
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 ff2ca36..04f4a88 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -2951,6 +2951,40 @@
-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 3b66da1..da99ffa 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 @@
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 29ea2d2..a2955c6 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 2f49aa9..257a1ad 100644
--- a/yotta/data/example-authcrypt/main.cpp
+++ b/yotta/data/example-authcrypt/main.cpp
@@ -187,7 +187,7 @@
}
void app_start(int, char*[]) {
- minar::Scheduler::postCallback(FunctionPointer0<void>(run).bind());
+ minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
}
#else
diff --git a/yotta/data/example-benchmark/main.cpp b/yotta/data/example-benchmark/main.cpp
index 6ac2a29..1a6c7ae 100644
--- a/yotta/data/example-benchmark/main.cpp
+++ b/yotta/data/example-benchmark/main.cpp
@@ -947,7 +947,7 @@
}
void app_start(int, char*[]) {
- minar::Scheduler::postCallback(FunctionPointer0<void>(run).bind());
+ minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
}
#endif /* TARGET_LIKE_MBED */
diff --git a/yotta/data/example-hashing/main.cpp b/yotta/data/example-hashing/main.cpp
index 4ef3665..7603cbe 100644
--- a/yotta/data/example-hashing/main.cpp
+++ b/yotta/data/example-hashing/main.cpp
@@ -167,7 +167,7 @@
}
void app_start(int, char*[]) {
- minar::Scheduler::postCallback(FunctionPointer0<void>(run).bind());
+ minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
}
#else
diff --git a/yotta/data/example-selftest/main.cpp b/yotta/data/example-selftest/main.cpp
index 22fd466..046a548 100644
--- a/yotta/data/example-selftest/main.cpp
+++ b/yotta/data/example-selftest/main.cpp
@@ -258,7 +258,7 @@
}
void app_start(int, char*[]) {
- minar::Scheduler::postCallback(FunctionPointer0<void>(run).bind());
+ minar::Scheduler::postCallback(mbed::util::FunctionPointer0<void>(run).bind());
}
#else
diff --git a/yotta/data/example-tls-client/main.cpp b/yotta/data/example-tls-client/main.cpp
index 684f1c1..907cfb6 100644
--- a/yotta/data/example-tls-client/main.cpp
+++ b/yotta/data/example-tls-client/main.cpp
@@ -513,7 +513,7 @@
printf("Client IP Address is %s\r\n", eth.getIPAddress());
- mbed::FunctionPointer1<void, const char*> fp(hello, &HelloHTTPS::startTest);
+ mbed::util::FunctionPointer1<void, const char*> fp(hello, &HelloHTTPS::startTest);
minar::Scheduler::postCallback(fp.bind(HTTPS_PATH));
}
diff --git a/yotta/data/module.json b/yotta/data/module.json
index 5b57cc2..848ad03 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" }
}
}