X-Git-Url: https://www.bearssl.org/gitweb//home/git/?p=BearSSL;a=blobdiff_plain;f=src%2Fssl%2Fssl_lru.c;h=4c71011f0885db79912c0a5185c6ea4dd9a95843;hp=4ddc97ab33d585a8d8dafc536ea480ad3920fc76;hb=12db697bccf2ff732665b9c7668c0826513489e0;hpb=d8641065c992e2d06494d51f151355635f05dfa0 diff --git a/src/ssl/ssl_lru.c b/src/ssl/ssl_lru.c index 4ddc97a..4c71011 100644 --- a/src/ssl/ssl_lru.c +++ b/src/ssl/ssl_lru.c @@ -54,6 +54,10 @@ * 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, mid, NULL); + if (addr != ADDR_NULL) { + br_enc16be(cc->store + addr + VERSION_OFF, 0); + } +}