tls13: Add function to search for a supported_versions extension
Move in a dedicated function the search for the
supported_versions extension in a list of
extensions, to be able to use it on server side
as well.
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 14a3c7e..e136c35 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -2048,6 +2048,32 @@
unsigned char **buf,
size_t *buf_len);
+/**
+ * \brief Detect if a list of extensions contains a supported_versions
+ * extension or not.
+ *
+ * \param[in] ssl SSL context
+ * \param[in] buf Address of the first byte of the extensions vector.
+ * \param[in] end End of the buffer containing the list of extensions.
+ * \param[out] extension_data If the extension is present, address of its first
+ * byte of data, NULL otherwise.
+ * \param[out] extension_data_end If the extension is present, address of the
+ * first byte immediately following the extension
+ * data, NULL otherwise.
+ * \return 0 if the list of extensions does not contain a supported_versions
+ * extension.
+ * \return 1 if the list of extensions contains a supported_versions
+ * extension.
+ * \return A negative value if an error occurred while parsing the
+ * extensions.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(
+ mbedtls_ssl_context *ssl,
+ const unsigned char *buf, const unsigned char *end,
+ const unsigned char **extension_data,
+ const unsigned char **extension_data_end);
+
/*
* Handler of TLS 1.3 server certificate message
*/
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index d10fbeb..fedb2be 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1324,8 +1324,8 @@
{
const unsigned char *p = buf;
size_t legacy_session_id_echo_len;
- size_t extensions_len;
- const unsigned char *extensions_end;
+ const unsigned char *supported_versions_ext;
+ const unsigned char *supported_versions_ext_end;
/*
* Check there is enough data to access the legacy_session_id_echo vector
@@ -1347,45 +1347,9 @@
MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len + 4);
p += legacy_session_id_echo_len + 4;
- /* Case of no extension */
- if (p == end) {
- return 0;
- }
-
- /* ...
- * Extension extensions<6..2^16-1>;
- * ...
- * struct {
- * ExtensionType extension_type; (2 bytes)
- * opaque extension_data<0..2^16-1>;
- * } Extension;
- */
- MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
- extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
- p += 2;
-
- /* Check extensions do not go beyond the buffer of data. */
- MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
- extensions_end = p + extensions_len;
-
- while (p < extensions_end) {
- unsigned int extension_type;
- size_t extension_data_len;
-
- MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
- extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
- extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
- p += 4;
-
- if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) {
- return 1;
- }
-
- MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
- p += extension_data_len;
- }
-
- return 0;
+ return mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(
+ ssl, p, end,
+ &supported_versions_ext, &supported_versions_ext_end);
}
/* Returns a negative value on failure, and otherwise
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 38077dd..1a10e75 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -86,6 +86,61 @@
return ret;
}
+int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(
+ mbedtls_ssl_context *ssl,
+ const unsigned char *buf, const unsigned char *end,
+ const unsigned char **extension_data,
+ const unsigned char **extension_data_end)
+{
+ const unsigned char *p = buf;
+ size_t extensions_len;
+ const unsigned char *extensions_end;
+
+ *extension_data = NULL;
+ *extension_data_end = NULL;
+
+ /* Case of no extension */
+ if (p == end) {
+ return 0;
+ }
+
+ /* ...
+ * Extension extensions<x..2^16-1>;
+ * ...
+ * struct {
+ * ExtensionType extension_type; (2 bytes)
+ * opaque extension_data<0..2^16-1>;
+ * } Extension;
+ */
+ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+ extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+ p += 2;
+
+ /* Check extensions do not go beyond the buffer of data. */
+ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
+ extensions_end = p + extensions_len;
+
+ while (p < extensions_end) {
+ unsigned int extension_type;
+ size_t extension_data_len;
+
+ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
+ extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+ extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+ p += 4;
+ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
+
+ if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) {
+ *extension_data = p;
+ *extension_data_end = p + extension_data_len;
+ return 1;
+ }
+ p += extension_data_len;
+ }
+
+ return 0;
+}
+
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
/*
* STATE HANDLING: Read CertificateVerify