ssl_cache: Add an interface to remove cache entry by session id

Signed-off-by: Pengyu Lv <pengyu.lv@arm.com>
diff --git a/include/mbedtls/ssl_cache.h b/include/mbedtls/ssl_cache.h
index 5cd1cd3..41ada54 100644
--- a/include/mbedtls/ssl_cache.h
+++ b/include/mbedtls/ssl_cache.h
@@ -123,6 +123,23 @@
                           size_t session_id_len,
                           const mbedtls_ssl_session *session);
 
+/**
+ * \brief          Remove the cache entry by the session ID
+ *                 (Thread-safe if MBEDTLS_THREADING_C is enabled)
+ *
+ * \param data            The SSL cache context to use.
+ * \param session_id      The pointer to the buffer holding the session ID
+ *                        associated to \p session.
+ * \param session_id_len  The length of \p session_id in bytes.
+ *
+ * \return                0: The cache entry for session with provided ID
+ *                           is removed or does not exist.
+ *                        1: Internal error.
+ */
+int mbedtls_ssl_cache_remove(void *data,
+                             unsigned char const *session_id,
+                             size_t session_id_len);
+
 #if defined(MBEDTLS_HAVE_TIME)
 /**
  * \brief          Set the cache timeout
diff --git a/library/ssl_cache.c b/library/ssl_cache.c
index 7c16e10..ff36b05 100644
--- a/library/ssl_cache.c
+++ b/library/ssl_cache.c
@@ -314,6 +314,59 @@
     return ret;
 }
 
+int mbedtls_ssl_cache_remove(void *data,
+                             unsigned char const *session_id,
+                             size_t session_id_len)
+{
+    int ret = 1;
+    mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
+    mbedtls_ssl_cache_entry *entry;
+    mbedtls_ssl_cache_entry *prev;
+
+#if defined(MBEDTLS_THREADING_C)
+    if (mbedtls_mutex_lock(&cache->mutex) != 0) {
+        return 1;
+    }
+#endif
+
+    ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry);
+    /* No valid entry found, exit with success */
+    if (ret != 0) {
+        ret = 0;
+        goto exit;
+    }
+
+    /* Now we remove the entry from the chain */
+    if (entry == cache->chain) {
+        cache->chain = entry->next;
+        goto free;
+    }
+    for (prev = cache->chain; prev->next != NULL; prev = prev->next) {
+        if (prev->next == entry) {
+            prev->next = entry->next;
+            break;
+        }
+    }
+
+free:
+    if (entry->session != NULL) {
+        mbedtls_platform_zeroize(entry->session, entry->session_len);
+        mbedtls_free(entry->session);
+    }
+    mbedtls_platform_zeroize(entry, sizeof(mbedtls_ssl_cache_entry));
+    mbedtls_free(entry);
+    ret = 0;
+
+exit:
+#if defined(MBEDTLS_THREADING_C)
+    if (mbedtls_mutex_unlock(&cache->mutex) != 0) {
+        ret = 1;
+    }
+#endif
+
+    return ret;
+}
+
 #if defined(MBEDTLS_HAVE_TIME)
 void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout)
 {