From 5443e011e480cd8f622b93e851c544938e1e5608 Mon Sep 17 00:00:00 2001
From: David Girault <dgirault@sevenhugs.com>
Date: Fri, 1 Feb 2019 17:56:17 +0100
Subject: [PATCH 2/5] altcp_tls: support for saving/restoring session
 information

According to mbedTLS source code and documentation, calls to
`mbedtls_ssl_conf_session_cache` and `mbedtls_ssl_conf_session_tickets_cb`
are only available if mbedTLS is configured for server mode (ie. MBEDTLS_SSL_SRV_C
is defined). This cannot be used on client mode to resume a previous session.

To allow session reuse in client mode, application must save session parameters
(including tickets provided by the server if any) after successfull connection
and restore them before attemting to reconnect. Since `alctp_close()` free the
structure, it cannot be used to store the required information.

So, two new API were added, directly wrapped to mbedTLS functions, allow application
to do that by itself.

Also added full declaration of `struct altcp_tls_session` in altcp_tls.h to allow
easier usage in application when using mbedTLS port.
---
 src/apps/altcp_tls/altcp_tls_mbedtls.c | 38 ++++++++++++++++++++++
 src/include/lwip/altcp_tls.h           | 44 ++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)

diff --git a/src/apps/altcp_tls/altcp_tls_mbedtls.c b/src/apps/altcp_tls/altcp_tls_mbedtls.c
index 5252e8bc..b464d7ff 100644
--- a/src/apps/altcp_tls/altcp_tls_mbedtls.c
+++ b/src/apps/altcp_tls/altcp_tls_mbedtls.c
@@ -639,6 +639,44 @@ altcp_tls_wrap(struct altcp_tls_config *config, struct altcp_pcb *inner_pcb)
   return ret;
 }
 
+void
+altcp_tls_init_session(struct altcp_tls_session *session)
+{
+  if (session)
+    mbedtls_ssl_session_init(&session->data);
+}
+
+err_t
+altcp_tls_get_session(struct altcp_pcb *conn, struct altcp_tls_session *session)
+{
+  if (session && conn && conn->state) {
+    altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
+    int ret = mbedtls_ssl_get_session(&state->ssl_context, &session->data);
+    return ret < 0 ? ERR_VAL : ERR_OK;
+  }
+  return ERR_ARG;
+}
+
+err_t
+altcp_tls_set_session(struct altcp_pcb *conn, struct altcp_tls_session *session)
+{
+  if (session && conn && conn->state) {
+    altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state;
+    int ret = -1;
+    if (session->data.start)
+      ret = mbedtls_ssl_set_session(&state->ssl_context, &session->data);
+    return ret < 0 ? ERR_VAL : ERR_OK;
+  }
+  return ERR_ARG;
+}
+
+void
+altcp_tls_free_session(struct altcp_tls_session *session)
+{
+  if (session)
+    mbedtls_ssl_session_free(&session->data);
+}
+
 void *
 altcp_tls_context(struct altcp_pcb *conn)
 {
diff --git a/src/include/lwip/altcp_tls.h b/src/include/lwip/altcp_tls.h
index 5f1cb7c4..fcb784d8 100644
--- a/src/include/lwip/altcp_tls.h
+++ b/src/include/lwip/altcp_tls.h
@@ -51,6 +51,13 @@
 
 #include "lwip/altcp.h"
 
+/* check if mbedtls port is enabled */
+#include "lwip/apps/altcp_tls_mbedtls_opts.h"
+/* allow session structure to be fully defined when using mbedtls port */
+#if LWIP_ALTCP_TLS_MBEDTLS
+#include "mbedtls/ssl.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -143,6 +150,43 @@ struct altcp_pcb *altcp_tls_alloc(void *arg, u8_t ip_type);
  */
 void *altcp_tls_context(struct altcp_pcb *conn);
 
+/** @ingroup altcp_tls
+ * ALTCP_TLS session handle, content depends on port (e.g. mbedtls)
+ */
+struct altcp_tls_session
+#if LWIP_ALTCP_TLS_MBEDTLS
+{
+    mbedtls_ssl_session data;
+}
+#endif
+;
+
+/** @ingroup altcp_tls
+ * Initialise a TLS session buffer.
+ * Real type depends on port (e.g. mbedtls use mbedtls_ssl_session)
+ */
+void altcp_tls_init_session(struct altcp_tls_session *dest);
+
+/** @ingroup altcp_tls
+ * Save current connected session to reuse it later. Should be called after altcp_connect() succeeded.
+ * Return error if saving session fail.
+ * Real type depends on port (e.g. mbedtls use mbedtls_ssl_session)
+ */
+err_t altcp_tls_get_session(struct altcp_pcb *conn, struct altcp_tls_session *dest);
+
+/** @ingroup altcp_tls
+ * Restore a previously saved session. Must be called before altcp_connect().
+ * Return error if cannot restore session.
+ * Real type depends on port (e.g. mbedtls use mbedtls_ssl_session)
+ */
+err_t altcp_tls_set_session(struct altcp_pcb *conn, struct altcp_tls_session *from);
+
+/** @ingroup altcp_tls
+ * Free allocated data inside a TLS session buffer.
+ * Real type depends on port (e.g. mbedtls use mbedtls_ssl_session)
+ */
+void altcp_tls_free_session(struct altcp_tls_session *dest);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.20.1

