Added function to forget saved session parameters (for tests).
authorThomas Pornin <pornin@bolet.org>
Wed, 26 Jul 2017 13:52:38 +0000 (15:52 +0200)
committerThomas Pornin <pornin@bolet.org>
Wed, 26 Jul 2017 13:52:38 +0000 (15:52 +0200)
inc/bearssl_ssl.h
src/ssl/ssl_lru.c

index d15cf55..45ac599 100644 (file)
@@ -3220,6 +3220,19 @@ typedef struct {
 void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc,
        unsigned char *store, size_t store_len);
 
+/**
+ * \brief Forget an entry in an LRU session cache.
+ *
+ * The session cache context must have been initialised. The entry
+ * with the provided session ID (of exactly 32 bytes) is looked for
+ * in the cache; if located, it is disabled.
+ *
+ * \param cc   session cache context.
+ * \param id   session ID to forget.
+ */
+void br_ssl_session_cache_lru_forget(
+       br_ssl_session_cache_lru *cc, const unsigned char *id);
+
 /**
  * \brief Context structure for a SSL server.
  *
index 4ddc97a..7a2036b 100644 (file)
  *   tree left child     4 bytes (big endian)
  *   tree right child    4 bytes (big endian)
  *
+ * If an entry has a protocol version set to 0, then it is "disabled":
+ * it was a session pushed to the cache at some point, but it has
+ * been explicitly removed.
+ *
  * We need to keep the tree balanced because an attacker could make
  * handshakes, selecting some specific sessions (by reusing them) to
  * try to make us make an imbalanced tree that makes lookups expensive
@@ -437,8 +441,18 @@ lru_load(const br_ssl_session_cache_class **ctx,
        mask_id(cc, params->session_id, id);
        x = find_node(cc, id, NULL);
        if (x != ADDR_NULL) {
-               params->version = br_dec16be(
-                       cc->store + x + VERSION_OFF);
+               unsigned version;
+
+               version = br_dec16be(cc->store + x + VERSION_OFF);
+               if (version == 0) {
+                       /*
+                        * Entry is disabled, we pretend we did not find it.
+                        * Notably, we don't move it to the front of the
+                        * LRU list.
+                        */
+                       return 0;
+               }
+               params->version = version;
                params->cipher_suite = br_dec16be(
                        cc->store + x + CIPHER_SUITE_OFF);
                memcpy(params->master_secret,
@@ -489,3 +503,35 @@ br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc,
        cc->tail = ADDR_NULL;
        cc->root = ADDR_NULL;
 }
+
+/* see bearssl_ssl.h */
+void br_ssl_session_cache_lru_forget(
+       br_ssl_session_cache_lru *cc, const unsigned char *id)
+{
+       unsigned char mid[SESSION_ID_LEN];
+       uint32_t addr;
+
+       /*
+        * If the cache is not initialised yet, then it is empty, and
+        * there is nothing to forget.
+        */
+       if (!cc->init_done) {
+               return;
+       }
+
+       /*
+        * Look for the node in the tree. If found, the entry is marked
+        * as "disabled"; it will be reused in due course, as it ages
+        * through the list.
+        *
+        * We do not go through the complex moves of actually releasing
+        * the entry right away because explicitly forgetting sessions
+        * should be a rare event, meant mostly for testing purposes,
+        * so this is not worth the extra code size.
+        */
+       mask_id(cc, id, mid);
+       addr = find_node(cc, id, NULL);
+       if (addr != ADDR_NULL) {
+               br_enc16be(cc->store + addr + VERSION_OFF, 0);
+       }
+}