> On 13 Oct 2023, at 19:13, Sergey Kandaurov <pluk...@nginx.com> wrote: > > [..] > > I was pondering on reusing a static crypto context > to make generating Retry packets more lightweight. > Known fixed values for key and nonce make it possible to create > a single context and reuse it over all Retry packets. > > Note that the context memory is kept for reuse after the first > retry, it will be freed eventually on process exit, > the operating system will take care of it. > Not sure though this is a good solution. > > diff --git a/src/event/quic/ngx_event_quic_protection.c > b/src/event/quic/ngx_event_quic_protection.c > --- a/src/event/quic/ngx_event_quic_protection.c > +++ b/src/event/quic/ngx_event_quic_protection.c > @@ -872,7 +872,6 @@ ngx_quic_create_retry_packet(ngx_quic_he > { > u_char *start; > ngx_str_t ad, itag; > - ngx_quic_secret_t secret; > ngx_quic_ciphers_t ciphers; > > /* 5.8. Retry Packet Integrity */ > @@ -882,6 +881,8 @@ ngx_quic_create_retry_packet(ngx_quic_he > "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; > static ngx_str_t in = ngx_string(""); > > + static ngx_quic_secret_t secret; > + > ad.data = res->data; > ad.len = ngx_quic_create_retry_itag(pkt, ad.data, &start); > > @@ -893,6 +894,10 @@ ngx_quic_create_retry_packet(ngx_quic_he > "quic retry itag len:%uz %xV", ad.len, &ad); > #endif > > + if (secret.ctx) { > + goto seal; > + } > + > if (ngx_quic_ciphers(0, &ciphers, pkt->level) == NGX_ERROR) { > return NGX_ERROR; > } > @@ -905,14 +910,14 @@ ngx_quic_create_retry_packet(ngx_quic_he > return NGX_ERROR; > } > > +seal: > + > if (ngx_quic_crypto_seal(&secret, &itag, nonce, &in, &ad, pkt->log) > != NGX_OK) > { > return NGX_ERROR; > } > > - ngx_quic_crypto_cleanup(&secret); > - > res->len = itag.data + itag.len - start; > res->data = start; > >
Another approach is to create a single context in the master process, used to cleanup the context in explicit manner on process shutdown. Note that ngx_quic_conf_t is already taken, had to pick a new one. # HG changeset patch # User Sergey Kandaurov <pluk...@nginx.com> # Date 1698099112 -14400 # Tue Oct 24 02:11:52 2023 +0400 # Node ID acdb54a32cdebf5cd987cf343b5e836e12d50967 # Parent af5ab04c7037f33960efc595cd76b4f4a0bf4a86 QUIC: reusing crypto context for Retry packets. diff --git a/src/event/quic/ngx_event_quic.c b/src/event/quic/ngx_event_quic.c --- a/src/event/quic/ngx_event_quic.c +++ b/src/event/quic/ngx_event_quic.c @@ -30,10 +30,13 @@ static ngx_int_t ngx_quic_handle_frames( static void ngx_quic_push_handler(ngx_event_t *ev); +static void *ngx_quic_create_conf(ngx_cycle_t *cycle); +static void ngx_quic_cleanup(void *data); + static ngx_core_module_t ngx_quic_module_ctx = { ngx_string("quic"), - NULL, + ngx_quic_create_conf, NULL }; @@ -1454,3 +1457,52 @@ ngx_quic_shutdown_quic(ngx_connection_t ngx_quic_finalize_connection(c, qc->shutdown_code, qc->shutdown_reason); } } + + +static void * +ngx_quic_create_conf(ngx_cycle_t *cycle) +{ + ngx_quic_ciphers_t ciphers; + ngx_pool_cleanup_t *cln; + ngx_quic_module_conf_t *qcf; + + /* RFC 9001, 5.8. Retry Packet Integrity */ + static ngx_quic_md_t key = { + NGX_QUIC_AES_128_KEY_LEN, + "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e" + }; + + qcf = ngx_pcalloc(cycle->pool, sizeof(ngx_quic_module_conf_t)); + if (qcf == NULL) { + return NULL; + } + + if (ngx_quic_ciphers(NGX_QUIC_INITIAL_CIPHER, &ciphers) == NGX_ERROR) { + return NULL; + } + + cln = ngx_pool_cleanup_add(cycle->pool, 0); + if (cln == NULL) { + return NULL; + } + + cln->handler = ngx_quic_cleanup; + cln->data = qcf; + + if (ngx_quic_crypto_init(ciphers.c, &qcf->retry, &key, 1, cycle->log) + == NGX_ERROR) + { + return NULL; + } + + return qcf; +} + + +static void +ngx_quic_cleanup(void *data) +{ + ngx_quic_module_conf_t *qcf = data; + + ngx_quic_crypto_cleanup(&qcf->retry); +} diff --git a/src/event/quic/ngx_event_quic_connection.h b/src/event/quic/ngx_event_quic_connection.h --- a/src/event/quic/ngx_event_quic_connection.h +++ b/src/event/quic/ngx_event_quic_connection.h @@ -41,6 +41,11 @@ typedef struct ngx_quic_keys_s ng #include <ngx_event_quic_socket.h> +typedef struct { + ngx_quic_secret_t retry; +} ngx_quic_module_conf_t; + + /* RFC 9002, 6.2.2. Handshakes and New Paths: kInitialRtt */ #define NGX_QUIC_INITIAL_RTT 333 /* ms */ @@ -293,4 +298,8 @@ void ngx_quic_connstate_dbg(ngx_connecti #define ngx_quic_connstate_dbg(c) #endif + +extern ngx_module_t ngx_quic_module; + + #endif /* _NGX_EVENT_QUIC_CONNECTION_H_INCLUDED_ */ diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -13,10 +13,6 @@ /* RFC 9001, 5.4.1. Header Protection Application: 5-byte mask */ #define NGX_QUIC_HP_LEN 5 -#define NGX_QUIC_AES_128_KEY_LEN 16 - -#define NGX_QUIC_INITIAL_CIPHER TLS1_3_CK_AES_128_GCM_SHA256 - static ngx_int_t ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest, const u_char *prk, size_t prk_len, @@ -929,15 +925,11 @@ ngx_quic_create_packet(ngx_quic_header_t static ngx_int_t ngx_quic_create_retry_packet(ngx_quic_header_t *pkt, ngx_str_t *res) { - u_char *start; - ngx_str_t ad, itag; - ngx_quic_md_t key; - ngx_quic_secret_t secret; - ngx_quic_ciphers_t ciphers; + u_char *start; + ngx_str_t ad, itag; + ngx_quic_module_conf_t *qcf; - /* 5.8. Retry Packet Integrity */ - static u_char key_data[16] = - "\xbe\x0c\x69\x0b\x9f\x66\x57\x5a\x1d\x76\x6b\x54\xe3\x68\xc8\x4e"; + /* RFC 9001, 5.8. Retry Packet Integrity */ static u_char nonce[NGX_QUIC_IV_LEN] = "\x46\x15\x99\xd3\x5d\x63\x2b\xf2\x23\x98\x25\xbb"; static ngx_str_t in = ngx_string(""); @@ -953,28 +945,15 @@ ngx_quic_create_retry_packet(ngx_quic_he "quic retry itag len:%uz %xV", ad.len, &ad); #endif - if (ngx_quic_ciphers(NGX_QUIC_INITIAL_CIPHER, &ciphers) == NGX_ERROR) { - return NGX_ERROR; - } + qcf = (ngx_quic_module_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, + ngx_quic_module); - key.len = sizeof(key_data); - ngx_memcpy(key.data, key_data, sizeof(key_data)); - - if (ngx_quic_crypto_init(ciphers.c, &secret, &key, 1, pkt->log) - == NGX_ERROR) + if (ngx_quic_crypto_seal(&qcf->retry, &itag, nonce, &in, &ad, pkt->log) + != NGX_OK) { return NGX_ERROR; } - if (ngx_quic_crypto_seal(&secret, &itag, nonce, &in, &ad, pkt->log) - != NGX_OK) - { - ngx_quic_crypto_cleanup(&secret); - return NGX_ERROR; - } - - ngx_quic_crypto_cleanup(&secret); - res->len = itag.data + itag.len - start; res->data = start; diff --git a/src/event/quic/ngx_event_quic_protection.h b/src/event/quic/ngx_event_quic_protection.h --- a/src/event/quic/ngx_event_quic_protection.h +++ b/src/event/quic/ngx_event_quic_protection.h @@ -23,6 +23,10 @@ /* largest hash used in TLS is SHA-384 */ #define NGX_QUIC_MAX_MD_SIZE 48 +#define NGX_QUIC_AES_128_KEY_LEN 16 + +#define NGX_QUIC_INITIAL_CIPHER TLS1_3_CK_AES_128_GCM_SHA256 + #ifdef OPENSSL_IS_BORINGSSL #define ngx_quic_cipher_t EVP_AEAD -- Sergey Kandaurov _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel