From: Neil Horman Date: Wed, 15 Jan 2025 16:40:49 +0000 (-0500) Subject: Add public api to create token cache for QUIC NEW_TOKENS X-Git-Tag: openssl-3.5.0-alpha1~241 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b1828dc23ac8824365713f2d050ca2a180927686;p=thirdparty%2Fopenssl.git Add public api to create token cache for QUIC NEW_TOKENS Reviewed-by: Matt Caswell Reviewed-by: Saša Nedvědický (Merged from https://github.com/openssl/openssl/pull/26517) --- diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h index a470d146575..e01de740c24 100644 --- a/include/internal/quic_ssl.h +++ b/include/internal/quic_ssl.h @@ -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); diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in index c62b9497730..393a3a0fa69 100644 --- a/include/openssl/ssl.h.in +++ b/include/openssl/ssl.h.in @@ -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) diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 16b5fb0f3c5..8a03483a8ac 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -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 * ----------------------------------- diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 3dd8376d6d6..9334af39a5d 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -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 diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 7cf82e717a6..b466f1b5962 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -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 diff --git a/util/libssl.num b/util/libssl.num index ee49b1a604f..bd442eaa75b 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -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: