]> 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>
Mon, 17 Feb 2025 16:27:33 +0000 (11:27 -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 c62b949773076a96b248a4ca85d2730b68b5ee53..393a3a0fa698ee889191108ea71577aeca5be379 100644 (file)
@@ -2307,6 +2307,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 3dd8376d6d61c3a85cb3be82876589b8a32d001d..9334af39a5dba8652402ecf070a82c7b6d4650f1 100644 (file)
@@ -4214,6 +4214,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)
@@ -4418,6 +4421,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);
 }
 
@@ -7979,6 +7986,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 7cf82e717a6d7835edb9ae50e16ae383d3c4a648..b466f1b5962b98fcf935d0c0806555705fedf8b3 100644 (file)
@@ -1201,6 +1201,7 @@ struct ssl_ctx_st {
 
 # ifndef OPENSSL_NO_QUIC
     uint64_t domain_flags;
+    SSL_TOKEN_STORE_HANDLE *tokencache;
 # endif
 
 # ifndef OPENSSL_NO_QLOG
index ee49b1a604faa661350a1a5e44671caf44c3707c..bd442eaa75b5412022b88b5f1e0b912469916598 100644 (file)
@@ -605,3 +605,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: