Latest update - GitHub 5b8a5c08c

This commit is contained in:
2025-05-29 13:38:31 +09:00
parent 5a9ef13268
commit 45064635e8
23 changed files with 834 additions and 275 deletions
+502 -117
View File
@@ -10,13 +10,6 @@
#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
*
@@ -25,43 +18,343 @@
#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 level, const SSL_CIPHER *cipher,
enum ssl_encryption_level_t ssl_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 level, const SSL_CIPHER *cipher,
enum ssl_encryption_level_t ssl_level, const SSL_CIPHER *cipher,
const uint8_t *secret, size_t secret_len);
#else
#else /* NGX_QUIC_QUICTLS_API */
static int ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t level, const uint8_t *read_secret,
enum ssl_encryption_level_t ssl_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 level, const uint8_t *data, size_t len);
enum ssl_encryption_level_t ssl_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 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);
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;
}
}
#if (NGX_QUIC_BORINGSSL_API)
static int
ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t level, const SSL_CIPHER *cipher,
enum ssl_encryption_level_t ssl_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((ngx_ssl_conn_t *) ssl_conn);
c = ngx_ssl_get_connection(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", level);
"quic ngx_quic_set_read_secret() level:%d", ssl_level);
#ifdef NGX_QUIC_DEBUG_CRYPTO
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic read secret len:%uz %*xs", secret_len,
@@ -72,7 +365,7 @@ ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn,
cipher, rsecret, secret_len)
!= NGX_OK)
{
return 0;
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
}
return 1;
@@ -81,17 +374,19 @@ 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 level, const SSL_CIPHER *cipher,
enum ssl_encryption_level_t ssl_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((ngx_ssl_conn_t *) ssl_conn);
c = ngx_ssl_get_connection(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", level);
"quic ngx_quic_set_write_secret() level:%d", ssl_level);
#ifdef NGX_QUIC_DEBUG_CRYPTO
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic write secret len:%uz %*xs", secret_len,
@@ -102,28 +397,31 @@ ngx_quic_set_write_secret(ngx_ssl_conn_t *ssl_conn,
cipher, wsecret, secret_len)
!= NGX_OK)
{
return 0;
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
}
return 1;
}
#else
#else /* NGX_QUIC_QUICTLS_API */
static int
ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t level, const uint8_t *rsecret,
enum ssl_encryption_level_t ssl_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((ngx_ssl_conn_t *) ssl_conn);
c = ngx_ssl_get_connection(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", level);
"quic ngx_quic_set_encryption_secrets() level:%d",
ssl_level);
#ifdef NGX_QUIC_DEBUG_CRYPTO
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic read secret len:%uz %*xs", secret_len,
@@ -136,10 +434,11 @@ ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
cipher, rsecret, secret_len)
!= NGX_OK)
{
return 0;
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
}
if (level == ssl_encryption_early_data) {
if (level == NGX_QUIC_ENCRYPTION_EARLY_DATA) {
return 1;
}
@@ -153,7 +452,7 @@ ngx_quic_set_encryption_secrets(ngx_ssl_conn_t *ssl_conn,
cipher, wsecret, secret_len)
!= NGX_OK)
{
return 0;
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
}
return 1;
@@ -164,24 +463,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 level, const uint8_t *data, size_t len)
enum ssl_encryption_level_t ssl_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((ngx_ssl_conn_t *) ssl_conn);
c = ngx_ssl_get_connection(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");
@@ -193,21 +492,20 @@ 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) {
qc->error = NGX_QUIC_ERR_CRYPTO(SSL_AD_NO_APPLICATION_PROTOCOL);
qc->error_reason = "unsupported protocol in ALPN extension";
if (qc->error == 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 unsupported protocol in ALPN extension");
return 0;
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"quic missing ALPN extension");
}
return 1;
}
#endif
SSL_get_peer_quic_transport_params(ssl_conn, &client_params,
&client_params_len);
@@ -217,12 +515,16 @@ 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";
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"missing transport parameters");
return 0;
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;
}
p = (u_char *) client_params;
@@ -237,11 +539,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 0;
return 1;
}
if (ngx_quic_apply_transport_params(c, &ctp) != NGX_OK) {
return 0;
return 1;
}
qc->client_tp_done = 1;
@@ -251,12 +553,14 @@ 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) {
return 0;
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
}
frame = ngx_quic_alloc_frame(c);
if (frame == NULL) {
return 0;
qc->error = NGX_QUIC_ERR_INTERNAL_ERROR;
return 1;
}
frame->data = out;
@@ -279,7 +583,7 @@ ngx_quic_flush_flight(ngx_ssl_conn_t *ssl_conn)
#if (NGX_DEBUG)
ngx_connection_t *c;
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
c = ngx_ssl_get_connection(ssl_conn);
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_flush_flight()");
@@ -289,17 +593,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 level,
uint8_t alert)
ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn,
enum ssl_encryption_level_t ssl_level, uint8_t alert)
{
ngx_connection_t *c;
ngx_quic_connection_t *qc;
c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
c = ngx_ssl_get_connection(ssl_conn);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"quic ngx_quic_send_alert() level:%s alert:%d",
ngx_quic_level_name(level), (int) alert);
"quic ngx_quic_send_alert() level:%d alert:%d",
ssl_level, (int) alert);
/* already closed on regular shutdown */
@@ -314,13 +618,14 @@ ngx_quic_send_alert(ngx_ssl_conn_t *ssl_conn, enum ssl_encryption_level_t level,
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;
@@ -343,13 +648,13 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
}
if (last <= ctx->crypto.offset) {
if (pkt->level == ssl_encryption_initial) {
if (pkt->level == NGX_QUIC_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, ssl_encryption_handshake);
ctx = ngx_quic_get_send_ctx(qc, NGX_QUIC_ENCRYPTION_HANDSHAKE);
while (!ngx_queue_empty(&ctx->sent)) {
ngx_quic_resend_frames(c, ctx);
}
@@ -359,43 +664,25 @@ ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
return NGX_OK;
}
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_write_buffer(c, &ctx->crypto, frame->data, f->length,
f->offset)
== NGX_CHAIN_ERROR)
{
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);
if (ngx_quic_crypto_provide(c, pkt->level) != NGX_OK) {
return NGX_ERROR;
}
return NGX_OK;
return ngx_quic_handshake(c);
}
static ngx_int_t
ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
enum ssl_encryption_level_t level)
ngx_quic_handshake(ngx_connection_t *c)
{
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;
@@ -404,20 +691,14 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
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);
@@ -433,13 +714,13 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
return NGX_ERROR;
}
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_do_handshake() failed");
ngx_ssl_connection_error(c, sslerr, 0, "SSL_do_handshake() failed");
return NGX_ERROR;
}
}
if (n <= 0 || SSL_in_init(ssl_conn)) {
if (ngx_quic_keys_available(qc->keys, ssl_encryption_early_data, 0)
if (!SSL_is_init_finished(ssl_conn)) {
if (ngx_quic_keys_available(qc->keys, NGX_QUIC_ENCRYPTION_EARLY_DATA, 0)
&& qc->client_tp_done)
{
if (ngx_quic_init_streams(c) != NGX_OK) {
@@ -461,7 +742,7 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
return NGX_ERROR;
}
frame->level = ssl_encryption_application;
frame->level = NGX_QUIC_ENCRYPTION_APPLICATION;
frame->type = NGX_QUIC_FT_HANDSHAKE_DONE;
ngx_quic_queue_frame(qc, frame);
@@ -485,7 +766,7 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
* An endpoint MUST discard its Handshake keys
* when the TLS handshake is confirmed.
*/
ngx_quic_discard_ctx(c, ssl_encryption_handshake);
ngx_quic_discard_ctx(c, NGX_QUIC_ENCRYPTION_HANDSHAKE);
ngx_quic_discover_path_mtu(c, qc->path);
@@ -502,17 +783,97 @@ ngx_quic_crypto_input(ngx_connection_t *c, ngx_chain_t *data,
}
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;
static SSL_QUIC_METHOD quic_method;
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
qc = ngx_quic_get_connection(c);
@@ -524,6 +885,20 @@ 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;
@@ -537,15 +912,17 @@ ngx_quic_init_connection(ngx_connection_t *c)
}
if (SSL_set_quic_method(ssl_conn, &quic_method) == 0) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
"quic SSL_set_quic_method() failed");
return NGX_ERROR;
}
#ifdef OPENSSL_INFO_QUIC
#if (NGX_QUIC_QUICTLS_API)
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);
@@ -577,15 +954,23 @@ 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_log_error(NGX_LOG_INFO, c->log, 0,
ngx_ssl_error(NGX_LOG_ALERT, 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_log_error(NGX_LOG_INFO, c->log, 0,
ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
"quic SSL_set_quic_early_data_context() failed");
return NGX_ERROR;
}