Compare commits

..

4 Commits

Author SHA1 Message Date
Sergey Kandaurov
481d28cb4e nginx-1.28.0-RELEASE 2025-04-23 15:48:54 +04:00
Roman Arutyunyan
55be5536a8 HTTP/3: fixed NGX_HTTP_V3_VARLEN_INT_LEN value.
After fixing ngx_http_v3_encode_varlen_int() in 400eb1b628,
NGX_HTTP_V3_VARLEN_INT_LEN retained the old value of 4, which is
insufficient for the values over 1073741823 (1G - 1).

The NGX_HTTP_V3_VARLEN_INT_LEN macro is used in ngx_http_v3_uni.c to
format stream and frame types.  Old buffer size is enough for formatting
this data.  Also, the macro is used in ngx_http_v3_filter_module.c to
format output chunks and trailers.  Considering output_buffers and
proxy_buffer_size are below 1G in all realistic scenarios, the old buffer
size is enough here as well.
2025-04-23 15:48:54 +04:00
Roman Arutyunyan
3a97c9616c Fixed -Wunterminated-string-initialization with gcc15. 2025-04-23 15:48:54 +04:00
Sergey Kandaurov
f2aa4339a5 Stable branch. 2025-04-23 15:48:54 +04:00
28 changed files with 315 additions and 846 deletions

View File

@ -26,10 +26,6 @@ ngx_msvc_ver=`echo $NGX_MSVC_VER | sed -e 's/^\([0-9]*\).*/\1/'`
case "$NGX_MSVC_VER" in
*ARM64)
NGX_MACHINE=arm64
;;
*x64)
NGX_MACHINE=amd64
;;

View File

@ -12,6 +12,7 @@ if [ $OPENSSL != NONE ]; then
if [ $USE_OPENSSL_QUIC = YES ]; then
have=NGX_QUIC . auto/have
have=NGX_QUIC_OPENSSL_COMPAT . auto/have
fi
case "$CC" in
@ -147,18 +148,14 @@ else
if [ $USE_OPENSSL_QUIC = YES ]; then
ngx_feature="OpenSSL QUIC API"
ngx_feature="OpenSSL QUIC support"
ngx_feature_name="NGX_QUIC"
ngx_feature_test="SSL_set_quic_tls_cbs(NULL, NULL, NULL)"
ngx_feature_test="SSL_set_quic_method(NULL, NULL)"
. auto/feature
if [ $ngx_found = no ]; then
ngx_feature="BoringSSL-like QUIC API"
ngx_feature_test="SSL_set_quic_method(NULL, NULL)"
. auto/feature
fi
have=NGX_QUIC_OPENSSL_COMPAT . auto/have
if [ $ngx_found = no ]; then
ngx_feature="OpenSSL QUIC compatibility"
ngx_feature_test="SSL_CTX_add_custom_ext(NULL, 0, 0,
NULL, NULL, NULL, NULL, NULL)"

View File

@ -13,10 +13,6 @@ case "$CC" in
OPENSSL_TARGET=VC-WIN64A
;;
arm64)
OPENSSL_TARGET=VC-WIN64-ARM
;;
*)
OPENSSL_TARGET=VC-WIN32
;;

View File

@ -118,19 +118,3 @@ ngx_feature_libs=
ngx_feature_test="int32_t lock = 0;
if (!OSAtomicCompareAndSwap32Barrier(0, 1, &lock)) return 1"
. auto/feature
ngx_feature="TCP_KEEPALIVE"
ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPALIVE, NULL, 0);
setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
. auto/feature
NGX_KEEPALIVE_CHECKED=YES

View File

@ -508,20 +508,18 @@ ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_DEFER_ACCEPT, NULL, 0)"
. auto/feature
if test -z "$NGX_KEEPALIVE_CHECKED"; then
ngx_feature="TCP_KEEPIDLE"
ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
. auto/feature
fi
ngx_feature="TCP_KEEPIDLE"
ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
. auto/feature
ngx_feature="TCP_FASTOPEN"

View File

@ -5,6 +5,42 @@
<change_log title="nginx">
<changes ver="1.28.0" date="2025-04-23">
<change>
<para lang="ru">
Стабильная ветка 1.28.x.
</para>
<para lang="en">
1.28.x stable branch.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx не собирался gcc 15,
если использовались модули ngx_http_v2_module и ngx_http_v3_module.
</para>
<para lang="en">
nginx could not be built by gcc 15
if ngx_http_v2_module or ngx_http_v3_module modules were used.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx мог не собираться gcc 14 и новее с оптимизацией -O3 -flto,
если использовался модуль ngx_http_v3_module.
</para>
<para lang="en">
nginx might not be built by gcc 14 or newer with -O3 -flto optimization
if ngx_http_v3_module was used.
</para>
</change>
</changes>
<changes ver="1.27.5" date="2025-04-16">
<change type="feature">

View File

@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
#define nginx_version 1029000
#define NGINX_VERSION "1.29.0"
#define nginx_version 1028000
#define NGINX_VERSION "1.28.0"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD

View File

@ -94,7 +94,7 @@ typedef intptr_t ngx_flag_t;
#ifndef NGX_ALIGNMENT
#define NGX_ALIGNMENT sizeof(uintptr_t) /* platform word */
#define NGX_ALIGNMENT sizeof(unsigned long) /* platform word */
#endif
#define ngx_align(d, a) (((d) + (a - 1)) & ~(a - 1))

View File

@ -765,8 +765,6 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
#if !(NGX_DARWIN)
if (ls[i].keepidle) {
value = ls[i].keepidle;
@ -784,8 +782,6 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
}
}
#endif
if (ls[i].keepintvl) {
value = ls[i].keepintvl;

View File

@ -203,23 +203,6 @@ ngx_event_accept(ngx_event_t *ev)
}
}
#if (NGX_HAVE_KEEPALIVE_TUNABLE && NGX_DARWIN)
/* Darwin doesn't inherit TCP_KEEPALIVE from a listening socket */
if (ls->keepidle) {
if (setsockopt(s, IPPROTO_TCP, TCP_KEEPALIVE,
(const void *) &ls->keepidle, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
"setsockopt(TCP_KEEPALIVE, %d) failed, ignored",
ls->keepidle);
}
}
#endif
*log = ls->log;
c->recv = ngx_recv;

View File

@ -45,6 +45,8 @@ static ssize_t ngx_ssl_sendfile(ngx_connection_t *c, ngx_buf_t *file,
size_t size);
static void ngx_ssl_read_handler(ngx_event_t *rev);
static void ngx_ssl_shutdown_handler(ngx_event_t *ev);
static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr,
ngx_err_t err, char *text);
static void ngx_ssl_clear_error(ngx_log_t *log);
static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
@ -1313,8 +1315,6 @@ ngx_ssl_passwords_cleanup(void *data)
ngx_int_t
ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
{
#ifndef OPENSSL_NO_DH
BIO *bio;
if (file->len == 0) {
@ -1385,8 +1385,6 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
BIO_free(bio);
#endif
return NGX_OK;
}
@ -3299,7 +3297,7 @@ ngx_ssl_shutdown_handler(ngx_event_t *ev)
}
void
static void
ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
char *text)
{

View File

@ -19,9 +19,7 @@
#include <openssl/bn.h>
#include <openssl/conf.h>
#include <openssl/crypto.h>
#ifndef OPENSSL_NO_DH
#include <openssl/dh.h>
#endif
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
@ -85,17 +83,6 @@
#endif
#ifdef OPENSSL_NO_DEPRECATED_3_4
#define SSL_SESSION_get_time(s) SSL_SESSION_get_time_ex(s)
#define SSL_SESSION_set_time(s, t) SSL_SESSION_set_time_ex(s, t)
#endif
#ifdef OPENSSL_NO_DEPRECATED_3_0
#define EVP_CIPHER_CTX_cipher(c) EVP_CIPHER_CTX_get0_cipher(c)
#endif
typedef struct ngx_ssl_ocsp_s ngx_ssl_ocsp_t;
@ -361,8 +348,6 @@ ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in,
off_t limit);
void ngx_ssl_free_buffer(ngx_connection_t *c);
ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c);
void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
char *text);
void ngx_cdecl ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
char *fmt, ...);
void ngx_ssl_cleanup_ctx(void *data);

View File

@ -8,16 +8,10 @@
#include <ngx_core.h>
#include <ngx_event.h>
#ifdef ERR_R_OSSL_STORE_LIB
#include <openssl/store.h>
#include <openssl/ui.h>
#endif
#define NGX_SSL_CACHE_PATH 0
#define NGX_SSL_CACHE_DATA 1
#define NGX_SSL_CACHE_ENGINE 2
#define NGX_SSL_CACHE_STORE 3
#define NGX_SSL_CACHE_DISABLED (ngx_array_t *) (uintptr_t) -1
@ -122,8 +116,6 @@ static void ngx_ssl_cache_node_insert(ngx_rbtree_node_t *temp,
static void ngx_ssl_cache_node_free(ngx_rbtree_t *rbtree,
ngx_ssl_cache_node_t *cn);
static ngx_int_t ngx_openssl_cache_init_worker(ngx_cycle_t *cycle);
static ngx_command_t ngx_openssl_cache_commands[] = {
@ -152,7 +144,7 @@ ngx_module_t ngx_openssl_cache_module = {
NGX_CORE_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
ngx_openssl_cache_init_worker, /* init process */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
@ -452,11 +444,6 @@ ngx_ssl_cache_init_key(ngx_pool_t *pool, ngx_uint_t index, ngx_str_t *path,
{
id->type = NGX_SSL_CACHE_ENGINE;
} else if (index == NGX_SSL_CACHE_PKEY
&& ngx_strncmp(path->data, "store:", sizeof("store:") - 1) == 0)
{
id->type = NGX_SSL_CACHE_STORE;
} else {
if (ngx_get_full_name(pool, (ngx_str_t *) &ngx_cycle->conf_prefix, path)
!= NGX_OK)
@ -727,6 +714,11 @@ ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data)
#endif
}
bio = ngx_ssl_cache_create_bio(id, err);
if (bio == NULL) {
return NULL;
}
cb_data.encrypted = 0;
if (*passwords) {
@ -742,76 +734,6 @@ ngx_ssl_cache_pkey_create(ngx_ssl_cache_key_t *id, char **err, void *data)
cb = NULL;
}
if (id->type == NGX_SSL_CACHE_STORE) {
#ifdef ERR_R_OSSL_STORE_LIB
u_char *uri;
UI_METHOD *method;
OSSL_STORE_CTX *store;
OSSL_STORE_INFO *info;
method = (cb != NULL) ? UI_UTIL_wrap_read_pem_callback(cb, 0) : NULL;
uri = id->data + sizeof("store:") - 1;
store = OSSL_STORE_open((char *) uri, method, pwd, NULL, NULL);
if (store == NULL) {
*err = "OSSL_STORE_open() failed";
if (method != NULL) {
UI_destroy_method(method);
}
return NULL;
}
pkey = NULL;
while (pkey == NULL && !OSSL_STORE_eof(store)) {
info = OSSL_STORE_load(store);
if (info == NULL) {
continue;
}
if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
pkey = OSSL_STORE_INFO_get1_PKEY(info);
}
OSSL_STORE_INFO_free(info);
}
OSSL_STORE_close(store);
if (method != NULL) {
UI_destroy_method(method);
}
if (pkey == NULL) {
*err = "OSSL_STORE_load() failed";
return NULL;
}
if (cb_data.encrypted) {
*passwords = NGX_SSL_CACHE_DISABLED;
}
return pkey;
#else
*err = "loading \"store:...\" certificate keys is not supported";
return NULL;
#endif
}
bio = ngx_ssl_cache_create_bio(id, err);
if (bio == NULL) {
return NULL;
}
for ( ;; ) {
pkey = PEM_read_bio_PrivateKey(bio, NULL, cb, pwd);
@ -1235,20 +1157,3 @@ ngx_ssl_cache_node_insert(ngx_rbtree_node_t *temp,
node->right = sentinel;
ngx_rbt_red(node);
}
static ngx_int_t
ngx_openssl_cache_init_worker(ngx_cycle_t *cycle)
{
#ifdef ERR_R_OSSL_STORE_LIB
if (ngx_process != NGX_PROCESS_WORKER) {
return NGX_OK;
}
UI_set_default_method(UI_null());
#endif
return NGX_OK;
}

View File

@ -72,7 +72,7 @@ ngx_quic_connstate_dbg(ngx_connection_t *c)
if (qc) {
if (qc->error) {
if (qc->error != (ngx_uint_t) -1) {
p = ngx_slprintf(p, last, "%s", qc->error_app ? " app" : "");
p = ngx_slprintf(p, last, " error:%ui", qc->error);
@ -135,9 +135,6 @@ ngx_quic_apply_transport_params(ngx_connection_t *c, ngx_quic_tp_t *ctp)
if (scid.len != ctp->initial_scid.len
|| ngx_memcmp(scid.data, ctp->initial_scid.data, scid.len) != 0)
{
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "invalid initial_source_connection_id";
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic client initial_source_connection_id mismatch");
return NGX_ERROR;
@ -260,9 +257,9 @@ ngx_quic_new_connection(ngx_connection_t *c, ngx_quic_conf_t *conf,
qc->send_ctx[i].pending_ack = NGX_QUIC_UNSET_PN;
}
qc->send_ctx[0].level = NGX_QUIC_ENCRYPTION_INITIAL;
qc->send_ctx[1].level = NGX_QUIC_ENCRYPTION_HANDSHAKE;
qc->send_ctx[2].level = NGX_QUIC_ENCRYPTION_APPLICATION;
qc->send_ctx[0].level = ssl_encryption_initial;
qc->send_ctx[1].level = ssl_encryption_handshake;
qc->send_ctx[2].level = ssl_encryption_application;
ngx_queue_init(&qc->free_frames);
@ -520,7 +517,7 @@ ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc)
* to terminate the connection immediately.
*/
if (qc->error == 0 && rc == NGX_ERROR) {
if (qc->error == (ngx_uint_t) -1) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
qc->error_app = 0;
}
@ -800,13 +797,13 @@ ngx_quic_handle_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
pkt->dcid.len, &pkt->dcid);
#if (NGX_DEBUG)
if (pkt->level != NGX_QUIC_ENCRYPTION_APPLICATION) {
if (pkt->level != ssl_encryption_application) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic packet rx scid len:%uz %xV",
pkt->scid.len, &pkt->scid);
}
if (pkt->level == NGX_QUIC_ENCRYPTION_INITIAL) {
if (pkt->level == ssl_encryption_initial) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic address validation token len:%uz %xV",
pkt->token.len, &pkt->token);
@ -823,7 +820,7 @@ ngx_quic_handle_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
return NGX_DECLINED;
}
if (pkt->level != NGX_QUIC_ENCRYPTION_APPLICATION) {
if (pkt->level != ssl_encryption_application) {
if (pkt->version != qc->version) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
@ -853,9 +850,7 @@ ngx_quic_handle_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
rc = ngx_quic_handle_payload(c, pkt);
if (rc == NGX_DECLINED
&& pkt->level == NGX_QUIC_ENCRYPTION_APPLICATION)
{
if (rc == NGX_DECLINED && pkt->level == ssl_encryption_application) {
if (ngx_quic_handle_stateless_reset(c, pkt) == NGX_OK) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic stateless reset packet detected");
@ -876,11 +871,11 @@ ngx_quic_handle_packet(ngx_connection_t *c, ngx_quic_conf_t *conf,
return ngx_quic_negotiate_version(c, pkt);
}
if (pkt->level == NGX_QUIC_ENCRYPTION_APPLICATION) {
if (pkt->level == ssl_encryption_application) {
return ngx_quic_send_stateless_reset(c, conf, pkt);
}
if (pkt->level != NGX_QUIC_ENCRYPTION_INITIAL) {
if (pkt->level != ssl_encryption_initial) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic expected initial, got handshake");
return NGX_ERROR;
@ -963,7 +958,7 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
qc = ngx_quic_get_connection(c);
qc->error = 0;
qc->error = (ngx_uint_t) -1;
qc->error_reason = 0;
c->log->action = "decrypting packet";
@ -975,10 +970,10 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
return NGX_DECLINED;
}
#if (NGX_QUIC_QUICTLS_API)
/* QuicTLS provides app read keys before completing handshake */
#if !defined (OPENSSL_IS_BORINGSSL)
/* OpenSSL provides read keys for an application level before it's ready */
if (pkt->level == NGX_QUIC_ENCRYPTION_APPLICATION && !c->ssl->handshaked) {
if (pkt->level == ssl_encryption_application && !c->ssl->handshaked) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic no %s keys ready, ignoring packet",
ngx_quic_level_name(pkt->level));
@ -1016,14 +1011,14 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
}
}
if (pkt->level == NGX_QUIC_ENCRYPTION_HANDSHAKE) {
if (pkt->level == ssl_encryption_handshake) {
/*
* RFC 9001, 4.9.1. Discarding Initial Keys
*
* The successful use of Handshake packets indicates
* that no more Initial packets need to be exchanged
*/
ngx_quic_discard_ctx(c, NGX_QUIC_ENCRYPTION_INITIAL);
ngx_quic_discard_ctx(c, ssl_encryption_initial);
if (!qc->path->validated) {
qc->path->validated = 1;
@ -1032,14 +1027,14 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
}
}
if (pkt->level == NGX_QUIC_ENCRYPTION_APPLICATION) {
if (pkt->level == ssl_encryption_application) {
/*
* RFC 9001, 4.9.3. Discarding 0-RTT Keys
*
* After receiving a 1-RTT packet, servers MUST discard
* 0-RTT keys within a short time
*/
ngx_quic_keys_discard(qc->keys, NGX_QUIC_ENCRYPTION_EARLY_DATA);
ngx_quic_keys_discard(qc->keys, ssl_encryption_early_data);
}
if (qc->closing) {
@ -1066,7 +1061,7 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
c->log->action = "handling payload";
if (pkt->level != NGX_QUIC_ENCRYPTION_APPLICATION) {
if (pkt->level != ssl_encryption_application) {
return ngx_quic_handle_frames(c, pkt);
}
@ -1091,7 +1086,7 @@ ngx_quic_handle_payload(ngx_connection_t *c, ngx_quic_header_t *pkt)
void
ngx_quic_discard_ctx(ngx_connection_t *c, ngx_uint_t level)
ngx_quic_discard_ctx(ngx_connection_t *c, enum ssl_encryption_level_t level)
{
ngx_queue_t *q;
ngx_quic_frame_t *f;
@ -1132,7 +1127,7 @@ ngx_quic_discard_ctx(ngx_connection_t *c, ngx_uint_t level)
ngx_quic_free_frame(c, f);
}
if (level == NGX_QUIC_ENCRYPTION_INITIAL) {
if (level == ssl_encryption_initial) {
/* close temporary listener with initial dcid */
qsock = ngx_quic_find_socket(c, NGX_QUIC_UNSET_PN);
if (qsock) {

View File

@ -12,21 +12,6 @@
#include <ngx_core.h>
#ifdef OSSL_RECORD_PROTECTION_LEVEL_NONE
#define NGX_QUIC_OPENSSL_API 1
#elif (defined SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION)
#define NGX_QUIC_QUICTLS_API 1
#elif (defined OPENSSL_IS_BORINGSSL || defined LIBRESSL_VERSION_NUMBER)
#define NGX_QUIC_BORINGSSL_API 1
#else
#define NGX_QUIC_BORINGSSL_API 1
#define NGX_QUIC_OPENSSL_COMPAT 1
#endif
#define NGX_QUIC_MAX_UDP_PAYLOAD_SIZE 65527
#define NGX_QUIC_DEFAULT_ACK_DELAY_EXPONENT 3

View File

@ -22,7 +22,7 @@
/* CUBIC parameters x10 */
#define NGX_QUIC_CUBIC_BETA 7
#define NGX_QUIC_CUBIC_C 4
#define MGX_QUIC_CUBIC_C 4
/* send time of ACK'ed packets */
@ -36,7 +36,7 @@ typedef struct {
static ngx_inline ngx_msec_t ngx_quic_time_threshold(ngx_quic_connection_t *qc);
static uint64_t ngx_quic_packet_threshold(ngx_quic_send_ctx_t *ctx);
static void ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
ngx_uint_t level, ngx_msec_t send_time);
enum ssl_encryption_level_t level, ngx_msec_t send_time);
static ngx_int_t ngx_quic_handle_ack_frame_range(ngx_connection_t *c,
ngx_quic_send_ctx_t *ctx, uint64_t min, uint64_t max,
ngx_quic_ack_stat_t *st);
@ -108,7 +108,7 @@ ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
ctx = ngx_quic_get_send_ctx(qc, pkt->level);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_handle_ack_frame level:%ui", pkt->level);
"quic ngx_quic_handle_ack_frame level:%d", pkt->level);
ack = &f->u.ack;
@ -207,7 +207,7 @@ ngx_quic_handle_ack_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
static void
ngx_quic_rtt_sample(ngx_connection_t *c, ngx_quic_ack_frame_t *ack,
ngx_uint_t level, ngx_msec_t send_time)
enum ssl_encryption_level_t level, ngx_msec_t send_time)
{
ngx_msec_t latest_rtt, ack_delay, adjusted_rtt, rttvar_sample;
ngx_quic_connection_t *qc;
@ -260,7 +260,7 @@ ngx_quic_handle_ack_frame_range(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
qc = ngx_quic_get_connection(c);
if (ctx->level == NGX_QUIC_ENCRYPTION_APPLICATION) {
if (ctx->level == ssl_encryption_application) {
if (ngx_quic_handle_path_mtu(c, qc->path, min, max) != NGX_OK) {
return NGX_ERROR;
}
@ -483,7 +483,7 @@ ngx_quic_congestion_cubic(ngx_connection_t *c)
* w_cubic = C * (t_msec / 1000) ^ 3 * mtu + w_max
*/
cc = 10000000000ll / (int64_t) cg->mtu / NGX_QUIC_CUBIC_C;
cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C;
w = t * t * t / cc + (int64_t) cg->w_max;
if (w > NGX_MAX_SIZE_T_VALUE) {
@ -634,7 +634,7 @@ ngx_quic_detect_lost(ngx_connection_t *c, ngx_quic_ack_stat_t *st)
wait = start->send_time + thr - now;
ngx_log_debug5(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic detect_lost pnum:%uL thr:%M pthr:%uL wait:%i level:%ui",
"quic detect_lost pnum:%uL thr:%M pthr:%uL wait:%i level:%d",
start->pnum, thr, pkt_thr, (ngx_int_t) wait, start->level);
if ((ngx_msec_int_t) wait > 0
@ -787,7 +787,7 @@ ngx_quic_resend_frames(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
switch (f->type) {
case NGX_QUIC_FT_ACK:
case NGX_QUIC_FT_ACK_ECN:
if (ctx->level == NGX_QUIC_ENCRYPTION_APPLICATION) {
if (ctx->level == ssl_encryption_application) {
/* force generation of most recent acknowledgment */
ctx->send_ack = NGX_QUIC_MAX_ACK_GAP;
}
@ -945,7 +945,7 @@ ngx_quic_congestion_cubic_time(ngx_connection_t *c)
return 0;
}
cc = 10000000000ll / (int64_t) cg->mtu / NGX_QUIC_CUBIC_C;
cc = 10000000000ll / (int64_t) cg->mtu / MGX_QUIC_CUBIC_C;
v = (int64_t) (cg->w_max - cg->window) * cc;
/*
@ -1073,7 +1073,7 @@ ngx_quic_pto(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
duration = qc->avg_rtt;
duration += ngx_max(4 * qc->rttvar, NGX_QUIC_TIME_GRANULARITY);
if (ctx->level == NGX_QUIC_ENCRYPTION_APPLICATION && c->ssl->handshaked) {
if (ctx->level == ssl_encryption_application && c->ssl->handshaked) {
duration += qc->ctp.max_ack_delay;
}
@ -1428,7 +1428,7 @@ ngx_quic_generate_ack(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx)
return NGX_OK;
}
if (ctx->level == NGX_QUIC_ENCRYPTION_APPLICATION) {
if (ctx->level == ssl_encryption_application) {
delay = ngx_current_msec - ctx->ack_delay_start;
qc = ngx_quic_get_connection(c);

View File

@ -17,15 +17,6 @@
/* #define NGX_QUIC_DEBUG_ALLOC */ /* log frames and bufs alloc */
/* #define NGX_QUIC_DEBUG_CRYPTO */
#define NGX_QUIC_ENCRYPTION_INITIAL 0
#define NGX_QUIC_ENCRYPTION_EARLY_DATA 1
#define NGX_QUIC_ENCRYPTION_HANDSHAKE 2
#define NGX_QUIC_ENCRYPTION_APPLICATION 3
#define NGX_QUIC_ENCRYPTION_LAST 4
#define NGX_QUIC_SEND_CTX_LAST (NGX_QUIC_ENCRYPTION_LAST - 1)
typedef struct ngx_quic_connection_s ngx_quic_connection_t;
typedef struct ngx_quic_server_id_s ngx_quic_server_id_t;
typedef struct ngx_quic_client_id_s ngx_quic_client_id_t;
@ -55,6 +46,8 @@ typedef struct ngx_quic_keys_s ngx_quic_keys_t;
#define NGX_QUIC_UNSET_PN (uint64_t) -1
#define NGX_QUIC_SEND_CTX_LAST (NGX_QUIC_ENCRYPTION_LAST - 1)
/* 0-RTT and 1-RTT data exist in the same packet number space,
* so we have 3 packet number spaces:
*
@ -63,9 +56,9 @@ typedef struct ngx_quic_keys_s ngx_quic_keys_t;
* 2 - 0-RTT and 1-RTT
*/
#define ngx_quic_get_send_ctx(qc, level) \
((level) == NGX_QUIC_ENCRYPTION_INITIAL) ? &((qc)->send_ctx[0]) \
: (((level) == NGX_QUIC_ENCRYPTION_HANDSHAKE) ? &((qc)->send_ctx[1]) \
: &((qc)->send_ctx[2]))
((level) == ssl_encryption_initial) ? &((qc)->send_ctx[0]) \
: (((level) == ssl_encryption_handshake) ? &((qc)->send_ctx[1]) \
: &((qc)->send_ctx[2]))
#define ngx_quic_get_connection(c) \
(((c)->udp) ? (((ngx_quic_socket_t *)((c)->udp))->quic) : NULL)
@ -195,7 +188,7 @@ typedef struct {
* are also Initial packets.
*/
struct ngx_quic_send_ctx_s {
ngx_uint_t level;
enum ssl_encryption_level_t level;
ngx_quic_buffer_t crypto;
uint64_t crypto_sent;
@ -286,7 +279,7 @@ struct ngx_quic_connection_s {
off_t received;
ngx_uint_t error;
ngx_uint_t error_level;
enum ssl_encryption_level_t error_level;
ngx_uint_t error_ftype;
const char *error_reason;
@ -301,17 +294,13 @@ struct ngx_quic_connection_s {
unsigned key_phase:1;
unsigned validated:1;
unsigned client_tp_done:1;
#if (NGX_QUIC_OPENSSL_API)
unsigned read_level:2;
unsigned write_level:2;
#endif
};
ngx_int_t ngx_quic_apply_transport_params(ngx_connection_t *c,
ngx_quic_tp_t *ctp);
void ngx_quic_discard_ctx(ngx_connection_t *c, ngx_uint_t level);
void ngx_quic_discard_ctx(ngx_connection_t *c,
enum ssl_encryption_level_t level);
void ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc);
void ngx_quic_shutdown_quic(ngx_connection_t *c);

View File

@ -99,7 +99,7 @@ ngx_quic_handle_new_connection_id_frame(ngx_connection_t *c,
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_RETIRE_CONNECTION_ID;
frame->u.retire_cid.sequence_number = f->seqnum;
@ -452,7 +452,7 @@ ngx_quic_send_server_id(ngx_connection_t *c, ngx_quic_server_id_t *sid)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_NEW_CONNECTION_ID;
frame->u.ncid.seqnum = sid->seqnum;
frame->u.ncid.retire = 0;
@ -485,7 +485,7 @@ ngx_quic_free_client_id(ngx_connection_t *c, ngx_quic_client_id_t *cid)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_RETIRE_CONNECTION_ID;
frame->u.retire_cid.sequence_number = cid->seqnum;

View File

@ -40,7 +40,7 @@ ngx_quic_handle_path_challenge_frame(ngx_connection_t *c,
ngx_quic_frame_t *fp;
ngx_quic_connection_t *qc;
if (pkt->level != NGX_QUIC_ENCRYPTION_APPLICATION || pkt->path_challenged) {
if (pkt->level != ssl_encryption_application || pkt->path_challenged) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ignoring PATH_CHALLENGE");
return NGX_OK;
@ -55,7 +55,7 @@ ngx_quic_handle_path_challenge_frame(ngx_connection_t *c,
return NGX_ERROR;
}
fp->level = NGX_QUIC_ENCRYPTION_APPLICATION;
fp->level = ssl_encryption_application;
fp->type = NGX_QUIC_FT_PATH_RESPONSE;
fp->u.path_response = *f;
@ -93,7 +93,7 @@ ngx_quic_handle_path_challenge_frame(ngx_connection_t *c,
return NGX_ERROR;
}
fp->level = NGX_QUIC_ENCRYPTION_APPLICATION;
fp->level = ssl_encryption_application;
fp->type = NGX_QUIC_FT_PING;
ngx_quic_queue_frame(qc, fp);
@ -177,7 +177,7 @@ valid:
if (rst) {
/* prevent old path packets contribution to congestion control */
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_APPLICATION);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
qc->rst_pnum = ctx->pnum;
ngx_memzero(&qc->congestion, sizeof(ngx_quic_congestion_t));
@ -549,7 +549,7 @@ ngx_quic_validate_path(ngx_connection_t *c, ngx_quic_path_t *path)
(void) ngx_quic_send_path_challenge(c, path);
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_APPLICATION);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
pto = ngx_max(ngx_quic_pto(c, ctx), 1000);
path->expires = ngx_current_msec + pto;
@ -579,7 +579,7 @@ ngx_quic_send_path_challenge(ngx_connection_t *c, ngx_quic_path_t *path)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_PATH_CHALLENGE;
ngx_memcpy(frame->u.path_challenge.data, path->challenge[n], 8);
@ -767,7 +767,7 @@ ngx_quic_expire_path_validation(ngx_connection_t *c, ngx_quic_path_t *path)
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_APPLICATION);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
if (++path->tries < NGX_QUIC_PATH_RETRIES) {
pto = ngx_max(ngx_quic_pto(c, ctx), 1000) << path->tries;
@ -830,7 +830,7 @@ ngx_quic_expire_path_mtu_delay(ngx_connection_t *c, ngx_quic_path_t *path)
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_APPLICATION);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
path->tries = 0;
@ -876,7 +876,7 @@ ngx_quic_expire_path_mtu_discovery(ngx_connection_t *c, ngx_quic_path_t *path)
ngx_quic_connection_t *qc;
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_APPLICATION);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
if (++path->tries < NGX_QUIC_PATH_RETRIES) {
rc = ngx_quic_send_path_mtu_probe(c, path);
@ -922,13 +922,13 @@ ngx_quic_send_path_mtu_probe(ngx_connection_t *c, ngx_quic_path_t *path)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_PING;
frame->ignore_loss = 1;
frame->ignore_congestion = 1;
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_APPLICATION);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
pnum = ctx->pnum;
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,

View File

@ -35,6 +35,8 @@ typedef struct {
ngx_str_t payload;
uint64_t number;
ngx_quic_compat_keys_t *keys;
enum ssl_encryption_level_t level;
} ngx_quic_compat_record_t;
@ -433,10 +435,11 @@ ngx_quic_compat_message_callback(int write_p, int version, int content_type,
case SSL3_RT_HANDSHAKE:
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic compat tx level:%d len:%uz", level, len);
"quic compat tx %s len:%uz ",
ngx_quic_level_name(level), len);
if (com->method->add_handshake_data(ssl, level, buf, len) != 1) {
return;
goto failed;
}
break;
@ -446,11 +449,11 @@ ngx_quic_compat_message_callback(int write_p, int version, int content_type,
alert = ((u_char *) buf)[1];
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic compat level:%d alert:%ui len:%uz",
level, alert, len);
"quic compat %s alert:%ui len:%uz ",
ngx_quic_level_name(level), alert, len);
if (com->method->send_alert(ssl, level, alert) != 1) {
return;
goto failed;
}
}
@ -458,6 +461,10 @@ ngx_quic_compat_message_callback(int write_p, int version, int content_type,
}
return;
failed:
ngx_post_event(&qc->close, &ngx_posted_events);
}
@ -480,8 +487,8 @@ SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level,
c = ngx_ssl_get_connection(ssl);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic compat rx level:%d len:%uz", level, len);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic compat rx %s len:%uz",
ngx_quic_level_name(level), len);
qc = ngx_quic_get_connection(c);
com = qc->compat;
@ -494,6 +501,7 @@ SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level,
rec.log = c->log;
rec.number = com->read_record++;
rec.keys = &com->keys;
rec.level = level;
if (level == ssl_encryption_initial) {
n = ngx_min(len, 65535);

View File

@ -7,6 +7,11 @@
#ifndef _NGX_EVENT_QUIC_OPENSSL_COMPAT_H_INCLUDED_
#define _NGX_EVENT_QUIC_OPENSSL_COMPAT_H_INCLUDED_
#if defined SSL_R_MISSING_QUIC_TRANSPORT_PARAMETERS_EXTENSION \
|| defined LIBRESSL_VERSION_NUMBER
#undef NGX_QUIC_OPENSSL_COMPAT
#else
#include <ngx_config.h>
#include <ngx_core.h>
@ -48,4 +53,7 @@ int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params,
void SSL_get_peer_quic_transport_params(const SSL *ssl,
const uint8_t **out_params, size_t *out_params_len);
#endif /* TLSEXT_TYPE_quic_transport_parameters */
#endif /* _NGX_EVENT_QUIC_OPENSSL_COMPAT_H_INCLUDED_ */

View File

@ -55,8 +55,7 @@ static ssize_t ngx_quic_send_segments(ngx_connection_t *c, u_char *buf,
size_t len, struct sockaddr *sockaddr, socklen_t socklen, size_t segment);
#endif
static ssize_t ngx_quic_output_packet(ngx_connection_t *c,
ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min,
ngx_uint_t ack_only);
ngx_quic_send_ctx_t *ctx, u_char *data, size_t max, size_t min);
static void ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
ngx_quic_header_t *pkt, ngx_quic_path_t *path);
static ngx_uint_t ngx_quic_get_padding_level(ngx_connection_t *c);
@ -132,7 +131,8 @@ ngx_quic_create_datagrams(ngx_connection_t *c)
ngx_memzero(preserved_pnum, sizeof(preserved_pnum));
#endif
do {
while (cg->in_flight < cg->window) {
p = dst;
len = ngx_quic_path_limit(c, path, path->mtu);
@ -158,8 +158,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c)
return NGX_OK;
}
n = ngx_quic_output_packet(c, ctx, p, len, min,
cg->in_flight >= cg->window);
n = ngx_quic_output_packet(c, ctx, p, len, min);
if (n == NGX_ERROR) {
return NGX_ERROR;
}
@ -188,8 +187,7 @@ ngx_quic_create_datagrams(ngx_connection_t *c)
ngx_quic_commit_send(c);
path->sent += len;
} while (cg->in_flight < cg->window);
}
return NGX_OK;
}
@ -294,17 +292,17 @@ ngx_quic_allow_segmentation(ngx_connection_t *c)
return 0;
}
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_INITIAL);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial);
if (!ngx_queue_empty(&ctx->frames)) {
return 0;
}
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_HANDSHAKE);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
if (!ngx_queue_empty(&ctx->frames)) {
return 0;
}
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_APPLICATION);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
bytes = 0;
len = ngx_min(qc->path->mtu, NGX_QUIC_MAX_UDP_SEGMENT_BUF);
@ -317,10 +315,6 @@ ngx_quic_allow_segmentation(ngx_connection_t *c)
bytes += f->len;
if (qc->congestion.in_flight + bytes >= qc->congestion.window) {
return 0;
}
if (bytes > len * 3) {
/* require at least ~3 full packets to batch */
return 1;
@ -349,7 +343,7 @@ ngx_quic_create_segments(ngx_connection_t *c)
cg = &qc->congestion;
path = qc->path;
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_APPLICATION);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_application);
if (ngx_quic_generate_ack(c, ctx) != NGX_OK) {
return NGX_ERROR;
@ -370,7 +364,7 @@ ngx_quic_create_segments(ngx_connection_t *c)
if (len && cg->in_flight + (p - dst) < cg->window) {
n = ngx_quic_output_packet(c, ctx, p, len, len, 0);
n = ngx_quic_output_packet(c, ctx, p, len, len);
if (n == NGX_ERROR) {
return NGX_ERROR;
}
@ -500,7 +494,7 @@ ngx_quic_get_padding_level(ngx_connection_t *c)
*/
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_INITIAL);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_initial);
for (q = ngx_queue_head(&ctx->frames);
q != ngx_queue_sentinel(&ctx->frames);
@ -527,7 +521,7 @@ ngx_quic_get_padding_level(ngx_connection_t *c)
static ssize_t
ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
u_char *data, size_t max, size_t min, ngx_uint_t ack_only)
u_char *data, size_t max, size_t min)
{
size_t len, pad, min_payload, max_payload;
u_char *p;
@ -591,10 +585,6 @@ ngx_quic_output_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
{
f = ngx_queue_data(q, ngx_quic_frame_t, queue);
if (ack_only && f->type != NGX_QUIC_FT_ACK) {
break;
}
if (len >= max_payload) {
break;
}
@ -687,10 +677,10 @@ ngx_quic_init_packet(ngx_connection_t *c, ngx_quic_send_ctx_t *ctx,
pkt->flags = NGX_QUIC_PKT_FIXED_BIT;
if (ctx->level == NGX_QUIC_ENCRYPTION_INITIAL) {
if (ctx->level == ssl_encryption_initial) {
pkt->flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_INITIAL;
} else if (ctx->level == NGX_QUIC_ENCRYPTION_HANDSHAKE) {
} else if (ctx->level == ssl_encryption_handshake) {
pkt->flags |= NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_HANDSHAKE;
} else {
@ -1103,7 +1093,7 @@ ngx_quic_send_new_token(ngx_connection_t *c, ngx_quic_path_t *path)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_NEW_TOKEN;
frame->data = out;
frame->u.token.length = token.len;

View File

@ -130,8 +130,8 @@ ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys, ngx_str_t *secret,
0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
};
client = &keys->secrets[NGX_QUIC_ENCRYPTION_INITIAL].client;
server = &keys->secrets[NGX_QUIC_ENCRYPTION_INITIAL].server;
client = &keys->secrets[ssl_encryption_initial].client;
server = &keys->secrets[ssl_encryption_initial].server;
/*
* RFC 9001, section 5. Packet Protection
@ -656,8 +656,8 @@ ngx_quic_crypto_hp_cleanup(ngx_quic_secret_t *s)
ngx_int_t
ngx_quic_keys_set_encryption_secret(ngx_log_t *log, ngx_uint_t is_write,
ngx_quic_keys_t *keys, ngx_uint_t level, const SSL_CIPHER *cipher,
const uint8_t *secret, size_t secret_len)
ngx_quic_keys_t *keys, enum ssl_encryption_level_t level,
const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len)
{
ngx_int_t key_len;
ngx_str_t secret_str;
@ -722,8 +722,8 @@ ngx_quic_keys_set_encryption_secret(ngx_log_t *log, ngx_uint_t is_write,
ngx_uint_t
ngx_quic_keys_available(ngx_quic_keys_t *keys, ngx_uint_t level,
ngx_uint_t is_write)
ngx_quic_keys_available(ngx_quic_keys_t *keys,
enum ssl_encryption_level_t level, ngx_uint_t is_write)
{
if (is_write == 0) {
return keys->secrets[level].client.ctx != NULL;
@ -734,7 +734,8 @@ ngx_quic_keys_available(ngx_quic_keys_t *keys, ngx_uint_t level,
void
ngx_quic_keys_discard(ngx_quic_keys_t *keys, ngx_uint_t level)
ngx_quic_keys_discard(ngx_quic_keys_t *keys,
enum ssl_encryption_level_t level)
{
ngx_quic_secret_t *client, *server;
@ -764,7 +765,7 @@ ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys)
{
ngx_quic_secrets_t *current, *next, tmp;
current = &keys->secrets[NGX_QUIC_ENCRYPTION_APPLICATION];
current = &keys->secrets[ssl_encryption_application];
next = &keys->next_key;
ngx_quic_crypto_cleanup(&current->client);
@ -793,7 +794,7 @@ ngx_quic_keys_update(ngx_event_t *ev)
qc = ngx_quic_get_connection(c);
keys = qc->keys;
current = &keys->secrets[NGX_QUIC_ENCRYPTION_APPLICATION];
current = &keys->secrets[ssl_encryption_application];
next = &keys->next_key;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "quic key update");

View File

@ -14,6 +14,8 @@
#include <ngx_event_quic_transport.h>
#define NGX_QUIC_ENCRYPTION_LAST ((ssl_encryption_application) + 1)
/* RFC 5116, 5.1/5.3 and RFC 8439, 2.3/2.5 for all supported ciphers */
#define NGX_QUIC_IV_LEN 12
#define NGX_QUIC_TAG_LEN 16
@ -92,11 +94,13 @@ typedef struct {
ngx_int_t ngx_quic_keys_set_initial_secret(ngx_quic_keys_t *keys,
ngx_str_t *secret, ngx_log_t *log);
ngx_int_t ngx_quic_keys_set_encryption_secret(ngx_log_t *log,
ngx_uint_t is_write, ngx_quic_keys_t *keys, ngx_uint_t level,
const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len);
ngx_uint_t ngx_quic_keys_available(ngx_quic_keys_t *keys, ngx_uint_t level,
ngx_uint_t is_write);
void ngx_quic_keys_discard(ngx_quic_keys_t *keys, ngx_uint_t level);
ngx_uint_t is_write, ngx_quic_keys_t *keys,
enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
const uint8_t *secret, size_t secret_len);
ngx_uint_t ngx_quic_keys_available(ngx_quic_keys_t *keys,
enum ssl_encryption_level_t level, ngx_uint_t is_write);
void ngx_quic_keys_discard(ngx_quic_keys_t *keys,
enum ssl_encryption_level_t level);
void ngx_quic_keys_switch(ngx_connection_t *c, ngx_quic_keys_t *keys);
void ngx_quic_keys_update(ngx_event_t *ev);
void ngx_quic_keys_cleanup(ngx_quic_keys_t *keys);

View File

@ -10,6 +10,13 @@
#include <ngx_event_quic_connection.h>
#if defined OPENSSL_IS_BORINGSSL \
|| defined LIBRESSL_VERSION_NUMBER \
|| NGX_QUIC_OPENSSL_COMPAT
#define NGX_QUIC_BORINGSSL_API 1
#endif
/*
* RFC 9000, 7.5. Cryptographic Message Buffering
*
@ -18,343 +25,43 @@
#define NGX_QUIC_MAX_BUFFERED 65535
#if (NGX_QUIC_OPENSSL_API)
static int ngx_quic_cbs_send(ngx_ssl_conn_t *ssl_conn,
const unsigned char *data, size_t len, size_t *consumed, void *arg);
static int ngx_quic_cbs_recv_rcd(ngx_ssl_conn_t *ssl_conn,
const unsigned char **data, size_t *bytes_read, void *arg);
static int ngx_quic_cbs_release_rcd(ngx_ssl_conn_t *ssl_conn,
size_t bytes_read, void *arg);
static int ngx_quic_cbs_yield_secret(ngx_ssl_conn_t *ssl_conn, uint32_t level,
int direction, const unsigned char *secret, size_t secret_len, void *arg);
static int ngx_quic_cbs_got_transport_params(ngx_ssl_conn_t *ssl_conn,
const unsigned char *params, size_t params_len, void *arg);
static int ngx_quic_cbs_alert(ngx_ssl_conn_t *ssl_conn, unsigned char alert,
void *arg);
#else /* NGX_QUIC_BORINGSSL_API || NGX_QUIC_QUICTLS_API */
static ngx_inline ngx_uint_t ngx_quic_map_encryption_level(
enum ssl_encryption_level_t ssl_level);
#if (NGX_QUIC_BORINGSSL_API)
static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, const SSL_CIPHER *cipher,
enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
const uint8_t *secret, size_t secret_len);
static int ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, const SSL_CIPHER *cipher,
enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
const uint8_t *secret, size_t secret_len);
#else /* NGX_QUIC_QUICTLS_API */
#else
static int ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, const uint8_t *read_secret,
enum ssl_encryption_level_t level, const uint8_t *read_secret,
const uint8_t *write_secret, size_t secret_len);
#endif
static int ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, const uint8_t *data, size_t len);
enum ssl_encryption_level_t level, const uint8_t *data, size_t len);
static int ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn);
static int ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, uint8_t alert);
#endif
static ngx_int_t ngx_quic_handshake(ngx_connection_t *c);
static ngx_int_t ngx_quic_crypto_provide(ngx_connection_t *c, ngx_uint_t level);
#if (NGX_QUIC_OPENSSL_API)
static int
ngx_quic_cbs_send(ngx_ssl_conn_t *ssl_conn,
const unsigned char *data, size_t len, size_t *consumed, void *arg)
{
ngx_connection_t *c = arg;
ngx_chain_t *out;
unsigned int alpn_len;
ngx_quic_frame_t *frame;
const unsigned char *alpn_data;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_cbs_send len:%uz", len);
qc = ngx_quic_get_connection(c);
*consumed = 0;
SSL_get0_alpn_selected(ssl_conn, &alpn_data, &alpn_len);
if (alpn_len == 0) {
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL);
qc->error_reason = "missing ALPN extension";
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic missing ALPN extension");
return 1;
}
if (!qc->client_tp_done) {
/* RFC 9001, 8.2. QUIC Transport Parameters Extension */
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION);
qc->error_reason = "missing transport parameters";
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"missing transport parameters");
return 1;
}
ctx = ngx_quic_get_send_ctx(qc, qc->write_level);
out = ngx_quic_copy_buffer(c, (u_char *) data, len);
if (out == NGX_CHAIN_ERROR) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
}
frame = ngx_quic_alloc_frame(c);
if (frame == NULL) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
}
frame->data = out;
frame->level = qc->write_level;
frame->type = NGX_QUIC_FT_CRYPTO;
frame->u.crypto.offset = ctx->crypto_sent;
frame->u.crypto.length = len;
ctx->crypto_sent += len;
*consumed = len;
ngx_quic_queue_frame(qc, frame);
return 1;
}
static int
ngx_quic_cbs_recv_rcd(ngx_ssl_conn_t *ssl_conn,
const unsigned char **data, size_t *bytes_read, void *arg)
{
ngx_connection_t *c = arg;
ngx_buf_t *b;
ngx_chain_t *cl;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_cbs_recv_rcd");
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, qc->read_level);
for (cl = ctx->crypto.chain; cl; cl = cl->next) {
b = cl->buf;
if (b->sync) {
/* hole */
*bytes_read = 0;
break;
}
*data = b->pos;
*bytes_read = b->last - b->pos;
break;
}
return 1;
}
static int
ngx_quic_cbs_release_rcd(ngx_ssl_conn_t *ssl_conn, size_t bytes_read, void *arg)
{
ngx_connection_t *c = arg;
ngx_chain_t *cl;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_cbs_release_rcd len:%uz", bytes_read);
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, qc->read_level);
cl = ngx_quic_read_buffer(c, &ctx->crypto, bytes_read);
if (cl == NGX_CHAIN_ERROR) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
}
ngx_quic_free_chain(c, cl);
return 1;
}
static int
ngx_quic_cbs_yield_secret(ngx_ssl_conn_t *ssl_conn, uint32_t ssl_level,
int direction, const unsigned char *secret, size_t secret_len, void *arg)
{
ngx_connection_t *c = arg;
ngx_uint_t level;
const SSL_CIPHER *cipher;
ngx_quic_connection_t *qc;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_cbs_yield_secret() level:%uD", ssl_level);
#ifdef NGX_QUIC_DEBUG_CRYPTO
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic %s secret len:%uz %*xs",
direction ? "write" : "read", secret_len,
secret_len, secret);
#endif
qc = ngx_quic_get_connection(c);
cipher = SSL_get_current_cipher(ssl_conn);
switch (ssl_level) {
case OSSL_RECORD_PROTECTION_LEVEL_NONE:
level = NGX_QUIC_ENCRYPTION_INITIAL;
break;
case OSSL_RECORD_PROTECTION_LEVEL_EARLY:
level = NGX_QUIC_ENCRYPTION_EARLY_DATA;
break;
case OSSL_RECORD_PROTECTION_LEVEL_HANDSHAKE:
level = NGX_QUIC_ENCRYPTION_HANDSHAKE;
break;
default: /* OSSL_RECORD_PROTECTION_LEVEL_APPLICATION */
level = NGX_QUIC_ENCRYPTION_APPLICATION;
break;
}
if (ngx_quic_keys_set_encryption_secret(c->log, direction, qc->keys, level,
cipher, secret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
}
if (direction) {
qc->write_level = level;
} else {
qc->read_level = level;
}
return 1;
}
static int
ngx_quic_cbs_got_transport_params(ngx_ssl_conn_t *ssl_conn,
const unsigned char *params, size_t params_len, void *arg)
{
ngx_connection_t *c = arg;
u_char *p, *end;
ngx_quic_tp_t ctp;
ngx_quic_connection_t *qc;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_cbs_got_transport_params() len:%uz",
params_len);
qc = ngx_quic_get_connection(c);
/* defaults for parameters not sent by client */
ngx_memcpy(&ctp, &qc->ctp, sizeof(ngx_quic_tp_t));
p = (u_char *) params;
end = p + params_len;
if (ngx_quic_parse_transport_params(p, end, &ctp, c->log) != NGX_OK) {
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "failed to process transport parameters";
return 1;
}
if (ngx_quic_apply_transport_params(c, &ctp) != NGX_OK) {
return 1;
}
qc->client_tp_done = 1;
return 1;
}
static int
ngx_quic_cbs_alert(ngx_ssl_conn_t *ssl_conn, unsigned char alert, void *arg)
{
ngx_connection_t *c = arg;
ngx_quic_connection_t *qc;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_cbs_alert() alert:%d", (int) alert);
/* already closed on regular shutdown */
qc = ngx_quic_get_connection(c);
if (qc == NULL) {
return 1;
}
qc->error = NGX_QUIC_ERR_CRYPTO(alert);
qc->error_reason = "handshake failed";
return 1;
}
#else /* NGX_QUIC_BORINGSSL_API || NGX_QUIC_QUICTLS_API */
static ngx_inline ngx_uint_t
ngx_quic_map_encryption_level(enum ssl_encryption_level_t ssl_level)
{
switch (ssl_level) {
case ssl_encryption_initial:
return NGX_QUIC_ENCRYPTION_INITIAL;
case ssl_encryption_early_data:
return NGX_QUIC_ENCRYPTION_EARLY_DATA;
case ssl_encryption_handshake:
return NGX_QUIC_ENCRYPTION_HANDSHAKE;
default: /* ssl_encryption_application */
return NGX_QUIC_ENCRYPTION_APPLICATION;
}
}
enum ssl_encryption_level_t level, uint8_t alert);
static ngx_int_t ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
enum ssl_encryption_level_t level);
#if (NGX_QUIC_BORINGSSL_API)
static int
ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, const SSL_CIPHER *cipher,
enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
const uint8_t *rsecret, size_t secret_len)
{
ngx_uint_t level;
ngx_connection_t *c;
ngx_quic_connection_t *qc;
c = ngx_ssl_get_connection(ssl_conn);
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
qc = ngx_quic_get_connection(c);
level = ngx_quic_map_encryption_level(ssl_level);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_set_read_secret() level:%d", ssl_level);
"quic ngx_quic_set_read_secret() level:%d", level);
#ifdef NGX_QUIC_DEBUG_CRYPTO
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic read secret len:%uz %*xs", secret_len,
@ -365,7 +72,7 @@ ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
cipher, rsecret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 0;
}
return 1;
@ -374,19 +81,17 @@ ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
static int
ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, const SSL_CIPHER *cipher,
enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
const uint8_t *wsecret, size_t secret_len)
{
ngx_uint_t level;
ngx_connection_t *c;
ngx_quic_connection_t *qc;
c = ngx_ssl_get_connection(ssl_conn);
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
qc = ngx_quic_get_connection(c);
level = ngx_quic_map_encryption_level(ssl_level);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_set_write_secret() level:%d", ssl_level);
"quic ngx_quic_set_write_secret() level:%d", level);
#ifdef NGX_QUIC_DEBUG_CRYPTO
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic write secret len:%uz %*xs", secret_len,
@ -397,31 +102,28 @@ ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
cipher, wsecret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 0;
}
return 1;
}
#else /* NGX_QUIC_QUICTLS_API */
#else
static int
ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, const uint8_t *rsecret,
enum ssl_encryption_level_t level, const uint8_t *rsecret,
const uint8_t *wsecret, size_t secret_len)
{
ngx_uint_t level;
ngx_connection_t *c;
const SSL_CIPHER *cipher;
ngx_quic_connection_t *qc;
c = ngx_ssl_get_connection(ssl_conn);
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
qc = ngx_quic_get_connection(c);
level = ngx_quic_map_encryption_level(ssl_level);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_set_encryption_secrets() level:%d",
ssl_level);
"quic ngx_quic_set_encryption_secrets() level:%d", level);
#ifdef NGX_QUIC_DEBUG_CRYPTO
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic read secret len:%uz %*xs", secret_len,
@ -434,11 +136,10 @@ ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
cipher, rsecret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
return 0;
}
if (level == NGX_QUIC_ENCRYPTION_EARLY_DATA) {
if (level == ssl_encryption_early_data) {
return 1;
}
@ -452,7 +153,7 @@ ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
cipher, wsecret, secret_len)
!= NGX_OK)
{
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 0;
}
return 1;
@ -463,24 +164,24 @@ ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
static int
ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, const uint8_t *data, size_t len)
enum ssl_encryption_level_t level, const uint8_t *data, size_t len)
{
u_char *p, *end;
size_t client_params_len;
ngx_uint_t level;
ngx_chain_t *out;
unsigned int alpn_len;
const uint8_t *client_params;
ngx_quic_tp_t ctp;
ngx_quic_frame_t *frame;
ngx_connection_t *c;
const unsigned char *alpn_data;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
unsigned int alpn_len;
const unsigned char *alpn_data;
#endif
c = ngx_ssl_get_connection(ssl_conn);
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
qc = ngx_quic_get_connection(c);
level = ngx_quic_map_encryption_level(ssl_level);
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_add_handshake_data");
@ -492,20 +193,21 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
* here;
*/
#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
SSL_get0_alpn_selected(ssl_conn, &alpn_data, &alpn_len);
if (alpn_len == 0) {
if (qc->error == 0) {
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL);
qc->error_reason = "missing ALPN extension";
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL);
qc->error_reason = "unsupported protocol in ALPN extension";
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic missing ALPN extension");
}
return 1;
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic unsupported protocol in ALPN extension");
return 0;
}
#endif
SSL_get_peer_quic_transport_params(ssl_conn, &client_params,
&client_params_len);
@ -515,16 +217,12 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
if (client_params_len == 0) {
/* RFC 9001, 8.2. QUIC Transport Parameters Extension */
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION);
qc->error_reason = "missing transport parameters";
if (qc->error == 0) {
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_MISSING_EXTENSION);
qc->error_reason = "missing transport parameters";
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"missing transport parameters");
}
return 1;
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"missing transport parameters");
return 0;
}
p = (u_char *) client_params;
@ -539,11 +237,11 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
qc->error = NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR;
qc->error_reason = "failed to process transport parameters";
return 1;
return 0;
}
if (ngx_quic_apply_transport_params(c, &ctp) != NGX_OK) {
return 1;
return 0;
}
qc->client_tp_done = 1;
@ -553,14 +251,12 @@ ngx_quic_add_handshake_data(ngx_ssl_conn_t *ssl_conn,
out = ngx_quic_copy_buffer(c, (u_char *) data, len);
if (out == NGX_CHAIN_ERROR) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
return 0;
}
frame = ngx_quic_alloc_frame(c);
if (frame == NULL) {
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
return 0;
}
frame->data = out;
@ -583,7 +279,7 @@ ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn)
#if (NGX_DEBUG)
ngx_connection_t *c;
c = ngx_ssl_get_connection(ssl_conn);
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_flush_flight()");
@ -593,17 +289,17 @@ ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn)
static int
ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, uint8_t alert)
ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
uint8_t alert)
{
ngx_connection_t *c;
ngx_quic_connection_t *qc;
c = ngx_ssl_get_connection(ssl_conn);
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_send_alert() level:%d alert:%d",
ssl_level, (int) alert);
"quic ngx_quic_send_alert() level:%s alert:%d",
ngx_quic_level_name(level), (int) alert);
/* already closed on regular shutdown */
@ -618,14 +314,13 @@ ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
return 1;
}
#endif
ngx_int_t
ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
ngx_quic_frame_t *frame)
{
uint64_t last;
ngx_chain_t *cl;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
ngx_quic_crypto_frame_t *f;
@ -648,13 +343,13 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
}
if (last <= ctx->crypto.offset) {
if (pkt->level == NGX_QUIC_ENCRYPTION_INITIAL) {
if (pkt->level == ssl_encryption_initial) {
/* speeding up handshake completion */
if (!ngx_queue_empty(&ctx->sent)) {
ngx_quic_resend_frames(c, ctx);
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_HANDSHAKE);
ctx = ngx_quic_get_send_ctx(qc, ssl_encryption_handshake);
while (!ngx_queue_empty(&ctx->sent)) {
ngx_quic_resend_frames(c, ctx);
}
@ -664,25 +359,43 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
return NGX_OK;
}
if (ngx_quic_write_buffer(c, &ctx->crypto, frame->data, f->length,
f->offset)
== NGX_CHAIN_ERROR)
{
return NGX_ERROR;
if (f->offset == ctx->crypto.offset) {
if (ngx_quic_crypto_input(c, frame->data, pkt->level) != NGX_OK) {
return NGX_ERROR;
}
ngx_quic_skip_buffer(c, &ctx->crypto, last);
} else {
if (ngx_quic_write_buffer(c, &ctx->crypto, frame->data, f->length,
f->offset)
== NGX_CHAIN_ERROR)
{
return NGX_ERROR;
}
}
if (ngx_quic_crypto_provide(c, pkt->level) != NGX_OK) {
return NGX_ERROR;
cl = ngx_quic_read_buffer(c, &ctx->crypto, (uint64_t) -1);
if (cl) {
if (ngx_quic_crypto_input(c, cl, pkt->level) != NGX_OK) {
return NGX_ERROR;
}
ngx_quic_free_chain(c, cl);
}
return ngx_quic_handshake(c);
return NGX_OK;
}
static ngx_int_t
ngx_quic_handshake(ngx_connection_t *c)
ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
enum ssl_encryption_level_t level)
{
int n, sslerr;
ngx_buf_t *b;
ngx_chain_t *cl;
ngx_ssl_conn_t *ssl_conn;
ngx_quic_frame_t *frame;
ngx_quic_connection_t *qc;
@ -691,14 +404,20 @@ ngx_quic_handshake(ngx_connection_t *c)
ssl_conn = c->ssl->connection;
for (cl = data; cl; cl = cl->next) {
b = cl->buf;
if (!SSL_provide_quic_data(ssl_conn, level, b->pos, b->last - b->pos)) {
ngx_ssl_error(NGX_LOG_INFO, c->log, 0,
"SSL_provide_quic_data() failed");
return NGX_ERROR;
}
}
n = SSL_do_handshake(ssl_conn);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
if (qc->error) {
return NGX_ERROR;
}
if (n <= 0) {
sslerr = SSL_get_error(ssl_conn, n);
@ -714,13 +433,13 @@ ngx_quic_handshake(ngx_connection_t *c)
return NGX_ERROR;
}
ngx_ssl_connection_error(c, sslerr, 0, "SSL_do_handshake() failed");
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed");
return NGX_ERROR;
}
}
if (!SSL_is_init_finished(ssl_conn)) {
if (ngx_quic_keys_available(qc->keys, NGX_QUIC_ENCRYPTION_EARLY_DATA, 0)
if (n <= 0 || SSL_in_init(ssl_conn)) {
if (ngx_quic_keys_available(qc->keys, ssl_encryption_early_data, 0)
&& qc->client_tp_done)
{
if (ngx_quic_init_streams(c) != NGX_OK) {
@ -742,7 +461,7 @@ ngx_quic_handshake(ngx_connection_t *c)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_HANDSHAKE_DONE;
ngx_quic_queue_frame(qc, frame);
@ -766,7 +485,7 @@ ngx_quic_handshake(ngx_connection_t *c)
* An endpoint MUST discard its Handshake keys
* when the TLS handshake is confirmed.
*/
ngx_quic_discard_ctx(c, NGX_QUIC_ENCRYPTION_HANDSHAKE);
ngx_quic_discard_ctx(c, ssl_encryption_handshake);
ngx_quic_discover_path_mtu(c, qc->path);
@ -783,97 +502,17 @@ ngx_quic_handshake(ngx_connection_t *c)
}
static ngx_int_t
ngx_quic_crypto_provide(ngx_connection_t *c, ngx_uint_t level)
{
#if (NGX_QUIC_BORINGSSL_API || NGX_QUIC_QUICTLS_API)
ngx_buf_t *b;
ngx_chain_t *out, *cl;
ngx_quic_send_ctx_t *ctx;
ngx_quic_connection_t *qc;
enum ssl_encryption_level_t ssl_level;
qc = ngx_quic_get_connection(c);
ctx = ngx_quic_get_send_ctx(qc, level);
out = ngx_quic_read_buffer(c, &ctx->crypto, (uint64_t) -1);
if (out == NGX_CHAIN_ERROR) {
return NGX_ERROR;
}
switch (level) {
case NGX_QUIC_ENCRYPTION_INITIAL:
ssl_level = ssl_encryption_initial;
break;
case NGX_QUIC_ENCRYPTION_EARLY_DATA:
ssl_level = ssl_encryption_early_data;
break;
case NGX_QUIC_ENCRYPTION_HANDSHAKE:
ssl_level = ssl_encryption_handshake;
break;
default: /* NGX_QUIC_ENCRYPTION_APPLICATION */
ssl_level = ssl_encryption_application;
break;
}
for (cl = out; cl; cl = cl->next) {
b = cl->buf;
if (!SSL_provide_quic_data(c->ssl->connection, ssl_level, b->pos,
b->last - b->pos))
{
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
"SSL_provide_quic_data() failed");
return NGX_ERROR;
}
}
ngx_quic_free_chain(c, out);
#endif
return NGX_OK;
}
ngx_int_t
ngx_quic_init_connection(ngx_connection_t *c)
{
u_char *p;
size_t clen;
ssize_t len;
ngx_str_t dcid;
ngx_ssl_conn_t *ssl_conn;
ngx_quic_socket_t *qsock;
ngx_quic_connection_t *qc;
#if (NGX_QUIC_OPENSSL_API)
static const OSSL_DISPATCH qtdis[] = {
{ OSSL_FUNC_SSL_QUIC_TLS_CRYPTO_SEND,
(void (*)(void)) ngx_quic_cbs_send },
{ OSSL_FUNC_SSL_QUIC_TLS_CRYPTO_RECV_RCD,
(void (*)(void)) ngx_quic_cbs_recv_rcd },
{ OSSL_FUNC_SSL_QUIC_TLS_CRYPTO_RELEASE_RCD,
(void (*)(void)) ngx_quic_cbs_release_rcd },
{ OSSL_FUNC_SSL_QUIC_TLS_YIELD_SECRET,
(void (*)(void)) ngx_quic_cbs_yield_secret },
{ OSSL_FUNC_SSL_QUIC_TLS_GOT_TRANSPORT_PARAMS,
(void (*)(void)) ngx_quic_cbs_got_transport_params },
{ OSSL_FUNC_SSL_QUIC_TLS_ALERT,
(void (*)(void)) ngx_quic_cbs_alert },
{ 0, NULL }
};
#else /* NGX_QUIC_BORINGSSL_API || NGX_QUIC_QUICTLS_API */
static SSL_QUIC_METHOD quic_method;
#endif
u_char *p;
size_t clen;
ssize_t len;
ngx_str_t dcid;
ngx_ssl_conn_t *ssl_conn;
ngx_quic_socket_t *qsock;
ngx_quic_connection_t *qc;
static SSL_QUIC_METHOD quic_method;
qc = ngx_quic_get_connection(c);
@ -885,20 +524,6 @@ ngx_quic_init_connection(ngx_connection_t *c)
ssl_conn = c->ssl->connection;
#if (NGX_QUIC_OPENSSL_API)
if (SSL_set_quic_tls_cbs(ssl_conn, qtdis, c) == 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
"quic SSL_set_quic_tls_cbs() failed");
return NGX_ERROR;
}
if (SSL_CTX_get_max_early_data(qc->conf->ssl->ctx)) {
SSL_set_quic_tls_early_data_enabled(ssl_conn, 1);
}
#else /* NGX_QUIC_BORINGSSL_API || NGX_QUIC_QUICTLS_API */
if (!quic_method.send_alert) {
#if (NGX_QUIC_BORINGSSL_API)
quic_method.set_read_secret = ngx_quic_set_read_secret;
@ -912,17 +537,15 @@ ngx_quic_init_connection(ngx_connection_t *c)
}
if (SSL_set_quic_method(ssl_conn, &quic_method) == 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic SSL_set_quic_method() failed");
return NGX_ERROR;
}
#if (NGX_QUIC_QUICTLS_API)
#ifdef OPENSSL_INFO_QUIC
if (SSL_CTX_get_max_early_data(qc->conf->ssl->ctx)) {
SSL_set_quic_early_data_enabled(ssl_conn, 1);
}
#endif
#endif
qsock = ngx_quic_get_socket(c);
@ -954,23 +577,15 @@ ngx_quic_init_connection(ngx_connection_t *c)
"quic transport parameters len:%uz %*xs", len, len, p);
#endif
#if (NGX_QUIC_OPENSSL_API)
if (SSL_set_quic_tls_transport_params(ssl_conn, p, len) == 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
"quic SSL_set_quic_tls_transport_params() failed");
return NGX_ERROR;
}
#else
if (SSL_set_quic_transport_params(ssl_conn, p, len) == 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic SSL_set_quic_transport_params() failed");
return NGX_ERROR;
}
#endif
#ifdef OPENSSL_IS_BORINGSSL
if (SSL_set_quic_early_data_context(ssl_conn, p, clen) == 0) {
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic SSL_set_quic_early_data_context() failed");
return NGX_ERROR;
}

View File

@ -280,7 +280,7 @@ ngx_quic_do_reset_stream(ngx_quic_stream_t *qs, ngx_uint_t err)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_RESET_STREAM;
frame->u.reset_stream.id = qs->id;
frame->u.reset_stream.error_code = err;
@ -367,7 +367,7 @@ ngx_quic_shutdown_stream_recv(ngx_connection_t *c)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0,
"quic stream id:0x%xL recv shutdown", qs->id);
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_STOP_SENDING;
frame->u.stop_sending.id = qs->id;
frame->u.stop_sending.error_code = qc->conf->stream_close_code;
@ -527,7 +527,7 @@ ngx_quic_reject_stream(ngx_connection_t *c, uint64_t id)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_RESET_STREAM;
frame->u.reset_stream.id = id;
frame->u.reset_stream.error_code = code;
@ -540,7 +540,7 @@ ngx_quic_reject_stream(ngx_connection_t *c, uint64_t id)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_STOP_SENDING;
frame->u.stop_sending.id = id;
frame->u.stop_sending.error_code = code;
@ -1062,7 +1062,7 @@ ngx_quic_stream_flush(ngx_quic_stream_t *qs)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_STREAM;
frame->data = out;
@ -1180,7 +1180,7 @@ ngx_quic_close_stream(ngx_quic_stream_t *qs)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_MAX_STREAMS;
if (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) {
@ -1771,7 +1771,7 @@ ngx_quic_update_max_stream_data(ngx_quic_stream_t *qs)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_MAX_STREAM_DATA;
frame->u.max_stream_data.id = qs->id;
frame->u.max_stream_data.limit = qs->recv_max_data;
@ -1807,7 +1807,7 @@ ngx_quic_update_max_data(ngx_connection_t *c)
return NGX_ERROR;
}
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->level = ssl_encryption_application;
frame->type = NGX_QUIC_FT_MAX_DATA;
frame->u.max_data.max_data = qc->streams.recv_max_data;

View File

@ -281,7 +281,7 @@ ngx_int_t
ngx_quic_parse_packet(ngx_quic_header_t *pkt)
{
if (!ngx_quic_long_pkt(pkt->flags)) {
pkt->level = NGX_QUIC_ENCRYPTION_APPLICATION;
pkt->level = ssl_encryption_application;
if (ngx_quic_parse_short_header(pkt, NGX_QUIC_SERVER_CID_LEN) != NGX_OK)
{
@ -468,13 +468,13 @@ ngx_quic_parse_long_header_v1(ngx_quic_header_t *pkt)
return NGX_ERROR;
}
pkt->level = NGX_QUIC_ENCRYPTION_INITIAL;
pkt->level = ssl_encryption_initial;
} else if (ngx_quic_pkt_zrtt(pkt->flags)) {
pkt->level = NGX_QUIC_ENCRYPTION_EARLY_DATA;
pkt->level = ssl_encryption_early_data;
} else if (ngx_quic_pkt_hs(pkt->flags)) {
pkt->level = NGX_QUIC_ENCRYPTION_HANDSHAKE;
pkt->level = ssl_encryption_handshake;
} else {
ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
@ -593,7 +593,7 @@ ngx_quic_payload_size(ngx_quic_header_t *pkt, size_t pkt_len)
/* flags, version, dcid and scid with lengths and zero-length token */
len = 5 + 2 + pkt->dcid.len + pkt->scid.len
+ (pkt->level == NGX_QUIC_ENCRYPTION_INITIAL ? 1 : 0);
+ (pkt->level == ssl_encryption_initial ? 1 : 0);
if (len > pkt_len) {
return 0;
@ -632,7 +632,7 @@ ngx_quic_create_long_header(ngx_quic_header_t *pkt, u_char *out,
if (out == NULL) {
return 5 + 2 + pkt->dcid.len + pkt->scid.len
+ ngx_quic_varint_len(rem_len) + pkt->num_len
+ (pkt->level == NGX_QUIC_ENCRYPTION_INITIAL ? 1 : 0);
+ (pkt->level == ssl_encryption_initial ? 1 : 0);
}
p = start = out;
@ -647,7 +647,7 @@ ngx_quic_create_long_header(ngx_quic_header_t *pkt, u_char *out,
*p++ = pkt->scid.len;
p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len);
if (pkt->level == NGX_QUIC_ENCRYPTION_INITIAL) {
if (pkt->level == ssl_encryption_initial) {
ngx_quic_build_int(&p, 0);
}
@ -1773,7 +1773,7 @@ ngx_quic_parse_transport_params(u_char *p, u_char *end, ngx_quic_tp_t *tp,
}
if (rc == NGX_DECLINED) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
ngx_log_error(NGX_LOG_INFO, log, 0,
"quic %s transport param id:0x%xL, skipped",
(id % 31 == 27) ? "reserved" : "unknown", id);
}

View File

@ -47,9 +47,9 @@
(ngx_quic_long_pkt(flags) ? 0x0F : 0x1F)
#define ngx_quic_level_name(lvl) \
(lvl == NGX_QUIC_ENCRYPTION_APPLICATION) ? "app" \
: (lvl == NGX_QUIC_ENCRYPTION_INITIAL) ? "init" \
: (lvl == NGX_QUIC_ENCRYPTION_HANDSHAKE) ? "hs" : "early"
(lvl == ssl_encryption_application) ? "app" \
: (lvl == ssl_encryption_initial) ? "init" \
: (lvl == ssl_encryption_handshake) ? "hs" : "early"
#define NGX_QUIC_MAX_CID_LEN 20
#define NGX_QUIC_SERVER_CID_LEN NGX_QUIC_MAX_CID_LEN
@ -262,7 +262,7 @@ typedef struct ngx_quic_frame_s ngx_quic_frame_t;
struct ngx_quic_frame_s {
ngx_uint_t type;
ngx_uint_t level;
enum ssl_encryption_level_t level;
ngx_queue_t queue;
uint64_t pnum;
size_t plen;
@ -310,7 +310,7 @@ typedef struct {
uint8_t flags;
uint32_t version;
ngx_str_t token;
ngx_uint_t level;
enum ssl_encryption_level_t level;
ngx_uint_t error;
/* filled in by parser */