Introduce configuration option and API for SSL record checking
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 529c07f..6e841c7 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1351,6 +1351,19 @@
 #define MBEDTLS_SSL_ALL_ALERT_MESSAGES
 
 /**
+ * \def MBEDTLS_SSL_RECORD_CHECKING
+ *
+ * Enable the API mbedtls_ssl_check_record() which allows to check the
+ * validity, freshness and authenticity of an incoming record without
+ * modifying the externally visible state of the SSL context.
+ *
+ * See mbedtls_ssl_check_record() for more information.
+ *
+ * Uncomment to enable support for record checking.
+ */
+#define MBEDTLS_SSL_RECORD_CHECKING
+
+/**
  * \def MBEDTLS_SSL_DTLS_CONNECTION_ID
  *
  * Enable support for the DTLS Connection ID extension
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 5f9862b..ba8d28e 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1756,6 +1756,54 @@
  */
 void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout );
 
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+/**
+ * \brief          Check whether a buffer contains a valid, fresh
+ *                 and authentic application data record (DTLS only).
+ *
+ *                 This function does not change the user-visible state
+ *                 of the SSL context. It's sole purpose is to provide
+ *                 an indication of the legitimacy of an incoming record.
+ *
+ *                 This can be useful e.g. in distributed server environments
+ *                 using the DTLS Connection ID feature, in which connections
+ *                 might need to be passed between service instances on a change
+ *                 of peer address, but where such disruptive operations should
+ *                 only happen after the validity of incoming records has been
+ *                 confirmed.
+ *
+ * \param ssl      The SSL context to use.
+ * \param buf      The address of the buffer holding the record to be checked.
+ *                 This must be an R/W buffer of length \p buflen Bytes.
+ * \param buflen   The length of \p buf in Bytes.
+ *
+ * \note           This routine only checks whether the provided buffer begins
+ *                 with a valid, fresh and authentic record, but does not check
+ *                 potential data following the initial record. In particular,
+ *                 it is possible to pass DTLS datagrams containing  records,
+ *                 in which case only the first record is checked.
+ *
+ * \note           This function modifies the input buffer \p buf. If you need
+ *                 to preserve the original record, you have to maintain a copy.
+ *
+ * \return         \c 0 if the record is valid, fresh (DTLS only) and authentic.
+ * \return         MBEDTLS_ERR_SSL_INVALID_MAC if the check completed
+ *                 successfully but the record was found to be not authentic.
+ * \return         MBEDTLS_ERR_SSL_INVALID_RECORD if the check completed
+ *                 successfully but the record was found to be invalid for
+ *                 a reason different from authenticity checking.
+ * \return         MBEDTLS_ERR_SSL_UNEXPECTED_RECORD if the check completed
+ *                 successfully but the record was found to be unexpected
+ *                 in the state of the SSL context, including replayed records.
+ * \return         Another negative error code on different kinds of failure.
+ *                 In this case, the SSL context becomes unusable and needs
+ *                 to be freed or reset before reuse.
+ */
+int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
+                              unsigned char *buf,
+                              size_t buflen );
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+
 /**
  * \brief          Set the timer callbacks (Mandatory for DTLS.)
  *
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 68a1e59..0386ea0 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -112,6 +112,18 @@
                                      mbedtls_ssl_transform *transform );
 static void ssl_update_in_pointers( mbedtls_ssl_context *ssl );
 
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
+                              unsigned char *buf,
+                              size_t buflen )
+{
+    ((void) ssl);
+    ((void) buf);
+    ((void) buflen);
+    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+}
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+
 #define SSL_DONT_FORCE_FLUSH 0
 #define SSL_FORCE_FLUSH      1
 
diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c
index 98a5df2..c6d19bf 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -1242,6 +1242,14 @@
     }
 #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */
 
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+    if( strcmp( "MBEDTLS_SSL_RECORD_CHECKING", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_RECORD_CHECKING );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     if( strcmp( "MBEDTLS_SSL_DTLS_CONNECTION_ID", config ) == 0 )
     {