]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add public api to create token cache for QUIC NEW_TOKENS
authorNeil Horman <nhorman@openssl.org>
Wed, 15 Jan 2025 16:40:49 +0000 (11:40 -0500)
committerNeil Horman <nhorman@openssl.org>
Tue, 4 Feb 2025 14:12:03 +0000 (09:12 -0500)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26517)

include/internal/quic_ssl.h
include/openssl/ssl.h.in
ssl/quic/quic_impl.c
ssl/ssl_lib.c
ssl/ssl_local.h
util/libssl.num

index a470d146575ecb7792e4fad52f4228125a27dab7..e01de740c2482e8eae6e459199dcc1cad3ddac63 100644 (file)
@@ -24,6 +24,12 @@ __owur SSL *ossl_quic_new_listener(SSL_CTX *ctx, uint64_t flags);
 __owur SSL *ossl_quic_new_listener_from(SSL *ssl, uint64_t flags);
 __owur SSL *ossl_quic_new_from_listener(SSL *ssl, uint64_t flags);
 __owur SSL *ossl_quic_new_domain(SSL_CTX *ctx, uint64_t flags);
+
+SSL_TOKEN_STORE_HANDLE *ossl_quic_new_token_store(void);
+void ossl_quic_free_token_store(SSL_TOKEN_STORE_HANDLE *hdl);
+SSL_TOKEN_STORE_HANDLE *ossl_quic_get_token_store(SSL_CTX *ctx);
+int ossl_quic_set_token_store(SSL_CTX *ctx, SSL_TOKEN_STORE_HANDLE *hdl);
+
 __owur int ossl_quic_init(SSL *s);
 void ossl_quic_deinit(SSL *s);
 void ossl_quic_free(SSL *s);
index 9ba1ab21f4d16c0614160695eb9556ca7cb0c289..249c164d9221bdf719b0642c66df24ddd5009688 100644 (file)
@@ -2297,6 +2297,10 @@ __owur int SSL_set1_initial_peer_addr(SSL *s, const BIO_ADDR *peer_addr);
 __owur SSL *SSL_get0_connection(SSL *s);
 __owur int SSL_is_connection(SSL *s);
 
+typedef void SSL_TOKEN_STORE_HANDLE;
+__owur SSL_TOKEN_STORE_HANDLE *SSL_CTX_get0_token_store(SSL_CTX *ctx);
+__owur int SSL_CTX_set_token_store(SSL_CTX *ctx, SSL_TOKEN_STORE_HANDLE *hdl);
+
 __owur int SSL_is_listener(SSL *ssl);
 __owur SSL *SSL_get0_listener(SSL *s);
 #define SSL_LISTENER_FLAG_NO_ACCEPT     (1UL << 0)
index 16b5fb0f3c5b7a31c04f3723acfae079165416d6..8a03483a8acd264ef28144616d6e01f42e6f15ec 100644 (file)
@@ -4623,6 +4623,124 @@ err:
     return NULL;
 }
 
+/*
+ * Token store management
+ */
+typedef struct quic_token_st {
+    uint8_t *hashkey;
+    size_t hashkey_len;
+    uint8_t *token;
+    size_t token_len;
+} QUIC_TOKEN;
+
+DEFINE_LHASH_OF_EX(QUIC_TOKEN);
+
+typedef struct ssl_token_store_st {
+    LHASH_OF(QUIC_TOKEN) *cache;
+    CRYPTO_REF_COUNT references;
+    CRYPTO_MUTEX *mutex;
+} SSL_TOKEN_STORE;
+
+static uint64_t fnv1a_hash_token(uint8_t *key, size_t len)
+{
+    uint64_t hash = 0xcbf29ce484222325ULL;
+    size_t i;
+
+    for (i = 0; i < len; i++) {
+        hash ^= key[i];
+        hash *= 0x00000100000001B3ULL;
+    }
+    return hash;
+}
+
+static unsigned long quic_token_hash(const QUIC_TOKEN *item)
+{
+    return (unsigned long)fnv1a_hash_token(item->hashkey, item->hashkey_len);
+}
+
+static int quic_token_cmp(const QUIC_TOKEN *a, const QUIC_TOKEN *b)
+{
+    if (a->hashkey_len != b->hashkey_len)
+        return 1;
+    return memcmp(a->hashkey, b->hashkey, a->hashkey_len);
+}
+
+SSL_TOKEN_STORE_HANDLE *ossl_quic_new_token_store(void)
+{
+    int ok = 0;
+    SSL_TOKEN_STORE *newcache = OPENSSL_zalloc(sizeof(SSL_TOKEN_STORE));
+
+    if (newcache == NULL)
+        goto out;
+
+    newcache->cache = lh_QUIC_TOKEN_new(quic_token_hash, quic_token_cmp);
+    if (newcache->cache == NULL)
+        goto out;
+
+#if defined(OPENSSL_THREADS)
+    if ((newcache->mutex = ossl_crypto_mutex_new()) == NULL)
+        goto out;
+#endif
+
+    if (!CRYPTO_NEW_REF(&newcache->references, 1))
+        goto out;
+
+    ok = 1;
+out:
+    if (!ok) {
+        ossl_quic_free_token_store(newcache);
+        newcache = NULL;
+    }
+    return (SSL_TOKEN_STORE_HANDLE *)newcache;
+}
+
+static void free_quic_token(QUIC_TOKEN *token)
+{
+    OPENSSL_free(token);
+}
+
+void ossl_quic_free_token_store(SSL_TOKEN_STORE_HANDLE *hdl)
+{
+    int refs;
+    SSL_TOKEN_STORE *c = (SSL_TOKEN_STORE *)hdl;
+
+    if (c == NULL)
+        return;
+
+    if (!CRYPTO_DOWN_REF(&c->references, &refs))
+        return;
+
+    if (refs > 0)
+        return;
+
+    /* last reference, we can clean up */
+    ossl_crypto_mutex_free(&c->mutex);
+    lh_QUIC_TOKEN_doall(c->cache, free_quic_token);
+    lh_QUIC_TOKEN_free(c->cache);
+    OPENSSL_free(c);
+    return;
+}
+
+SSL_TOKEN_STORE_HANDLE *ossl_quic_get_token_store(SSL_CTX *ctx)
+{
+    return ctx->tokencache;
+}
+
+int ossl_quic_set_token_store(SSL_CTX *ctx, SSL_TOKEN_STORE_HANDLE *hdl)
+{
+    SSL_TOKEN_STORE *new = hdl;
+    SSL_TOKEN_STORE_HANDLE *old = ctx->tokencache;
+    int ref;
+
+    if (!CRYPTO_UP_REF(&new->references, &ref))
+        return 0;
+
+    ctx->tokencache = new;
+
+    ossl_quic_free_token_store(old);
+    return 1;
+}
+
 /*
  * SSL_get_accept_connection_queue_len
  * -----------------------------------
index 2ba86454d44ba207fa8c90eb5da673a4a399d8d4..17ab6c7c35d52c34207bcd89a1f419230f505bac 100644 (file)
@@ -4191,6 +4191,9 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
     ret->num_tickets = 2;
 
 # ifndef OPENSSL_NO_QUIC
+    /* only create a cache for client CTX-es */
+    if (meth == OSSL_QUIC_client_method())
+        ret->tokencache = ossl_quic_new_token_store();
     ret->domain_flags = 0;
     if (IS_QUIC_METHOD(meth)) {
 #  if defined(OPENSSL_THREADS)
@@ -4393,6 +4396,10 @@ void SSL_CTX_free(SSL_CTX *a)
     OPENSSL_free(a->qlog_title);
 #endif
 
+#ifndef OPENSSL_NO_QUIC
+    ossl_quic_free_token_store(a->tokencache);
+#endif
+
     OPENSSL_free(a);
 }
 
@@ -7954,6 +7961,24 @@ SSL *SSL_new_from_listener(SSL *ssl, uint64_t flags)
 #endif
 }
 
+SSL_TOKEN_STORE_HANDLE *SSL_CTX_get0_token_store(SSL_CTX *ctx)
+{
+#ifndef OPENSSL_NO_QUIC
+    return ossl_quic_get_token_store(ctx);
+#else
+    return NULL;
+#endif
+}
+
+int SSL_CTX_set_token_store(SSL_CTX *ctx, SSL_TOKEN_STORE_HANDLE *hdl)
+{
+#ifndef OPENSSL_NO_QUIC
+    return ossl_quic_set_token_store(ctx, hdl);
+#else
+    return 0;
+#endif
+}
+
 SSL *SSL_accept_connection(SSL *ssl, uint64_t flags)
 {
 #ifndef OPENSSL_NO_QUIC
index 1b201ca679284084c0d333c13d3cf4d6833c16a4..3358abd0cb3a6baa94e8b0cfda32fcb3f6e05dea 100644 (file)
@@ -1188,6 +1188,7 @@ struct ssl_ctx_st {
 
 # ifndef OPENSSL_NO_QUIC
     uint64_t domain_flags;
+    SSL_TOKEN_STORE_HANDLE *tokencache;
 # endif
 
 # ifndef OPENSSL_NO_QLOG
index 26d665bfd817237c4016248d2a08b6d1bee8c167..bc93098b4e7d9eb301fffb61088e0ca175fc86b3 100644 (file)
@@ -603,3 +603,5 @@ SSL_CTX_set_domain_flags                ?   3_5_0   EXIST::FUNCTION:
 SSL_CTX_get_domain_flags                ?      3_5_0   EXIST::FUNCTION:
 SSL_get_domain_flags                    ?      3_5_0   EXIST::FUNCTION:
 SSL_CTX_set_new_pending_conn_cb         ?      3_5_0   EXIST::FUNCTION:
+SSL_CTX_get0_token_store                ?      3_5_0   EXIST::FUNCTION:
+SSL_CTX_set_token_store                 ?      3_5_0   EXIST::FUNCTION: