Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions deps/ngtcp2/ngtcp2/crypto/ossl/ossl.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ static void crypto_buf_write(crypto_buf *cbuf, const uint8_t *data,

struct ngtcp2_crypto_ossl_ctx {
SSL *ssl;
ngtcp2_encryption_level rx_level;
ngtcp2_encryption_level tx_level;
crypto_buf *crypto_head, *crypto_read, *crypto_write;
size_t crypto_head_released;
Expand All @@ -425,6 +426,7 @@ int ngtcp2_crypto_ossl_ctx_new(ngtcp2_crypto_ossl_ctx **possl_ctx, SSL *ssl) {
}

ossl_ctx->ssl = ssl;
ossl_ctx->rx_level = NGTCP2_ENCRYPTION_LEVEL_INITIAL;
ossl_ctx->tx_level = NGTCP2_ENCRYPTION_LEVEL_INITIAL;
ossl_ctx->crypto_head = ossl_ctx->crypto_read = ossl_ctx->crypto_write = NULL;
ossl_ctx->crypto_head_released = 0;
Expand Down Expand Up @@ -962,7 +964,10 @@ int ngtcp2_crypto_read_write_crypto_data(
SSL *ssl = ossl_ctx->ssl;
int rv;
int err;
(void)encryption_level;

if (encryption_level != ossl_ctx->rx_level) {
return -1;
}

if (crypto_ossl_ctx_write_crypto_data(ossl_ctx, data, datalen) != 0) {
return -1;
Expand Down Expand Up @@ -1128,7 +1133,10 @@ static int ossl_yield_secret(SSL *ssl, uint32_t ossl_level, int direction,
return 0;
}

ossl_ctx->tx_level = level;
/* CRYPTO data is never sent in 0-RTT packet. */
if (level != NGTCP2_ENCRYPTION_LEVEL_0RTT) {
ossl_ctx->tx_level = level;
}

return 1;
}
Expand All @@ -1138,6 +1146,11 @@ static int ossl_yield_secret(SSL *ssl, uint32_t ossl_level, int direction,
return 0;
}

/* This check is probably not needed, but just in case */
if (level != NGTCP2_ENCRYPTION_LEVEL_0RTT) {
ossl_ctx->rx_level = level;
}

return 1;
}

Expand Down
6 changes: 4 additions & 2 deletions deps/ngtcp2/ngtcp2/crypto/picotls/picotls.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,11 @@ int ngtcp2_crypto_read_write_crypto_data(
size_t i;
int rv;

ptls_buffer_init(&sendbuf, (void *)"", 0);
if (epoch != ptls_get_read_epoch(cptls->ptls)) {
return -1;
}

assert(datalen == 0 || epoch == ptls_get_read_epoch(cptls->ptls));
ptls_buffer_init(&sendbuf, (void *)"", 0);

rv = ptls_handle_message(cptls->ptls, &sendbuf, epoch_offsets, epoch, data,
datalen, &cptls->handshake_properties);
Expand Down
35 changes: 32 additions & 3 deletions deps/ngtcp2/ngtcp2/crypto/shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,35 @@ int ngtcp2_crypto_update_traffic_secret(uint8_t *dest, uint32_t version,
return 0;
}

/*
* crypto_set_remote_transport_params retrieves remote QUIC transport
* parameters from |tls| and sets it to |conn|. Some TLS backends set
* them to |conn| from their own TLS extension callback instead, which
* is never called if a remote endpoint omits the extension. This
* function fails if they have not been set to |conn| after all.
*
* This function returns 0 if it succeeds, or -1.
*/
static int crypto_set_remote_transport_params(ngtcp2_conn *conn, void *tls) {
const ngtcp2_transport_params *params;

if (ngtcp2_crypto_set_remote_transport_params(conn, tls) != 0) {
return -1;
}

params = ngtcp2_conn_get_remote_transport_params2(conn);

/* Client might have the remembered 0-RTT transport parameters, but
they never include initial_scid which is mandatory in the ones
received from a remote endpoint. */
if (!params || !params->initial_scid_present) {
ngtcp2_conn_set_tls_error(conn, NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM);
return -1;
}

return 0;
}

int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key,
uint8_t *iv, uint8_t *hp_key,
ngtcp2_encryption_level level,
Expand Down Expand Up @@ -282,7 +311,7 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key,
case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE:
if (ngtcp2_conn_is_server2(conn) &&
!ngtcp2_conn_get_negotiated_version2(conn)) {
rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
rv = crypto_set_remote_transport_params(conn, tls);
if (rv != 0) {
return -1;
}
Expand Down Expand Up @@ -340,7 +369,7 @@ int ngtcp2_crypto_derive_and_install_rx_key(ngtcp2_conn *conn, uint8_t *key,
break;
case NGTCP2_ENCRYPTION_LEVEL_1RTT:
if (!ngtcp2_conn_is_server2(conn)) {
rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
rv = crypto_set_remote_transport_params(conn, tls);
if (rv != 0) {
goto fail;
}
Expand Down Expand Up @@ -443,7 +472,7 @@ int ngtcp2_crypto_derive_and_install_tx_key(ngtcp2_conn *conn, uint8_t *key,
case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE:
if (ngtcp2_conn_is_server2(conn) &&
!ngtcp2_conn_get_negotiated_version2(conn)) {
rv = ngtcp2_crypto_set_remote_transport_params(conn, tls);
rv = crypto_set_remote_transport_params(conn, tls);
if (rv != 0) {
return -1;
}
Expand Down
3 changes: 2 additions & 1 deletion deps/ngtcp2/ngtcp2/examples/client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1721,7 +1721,8 @@ std::expected<void, Error> Client::make_stream_early() {
void Client::on_extend_max_streams() {
int64_t stream_id;

if ((config.delay_stream && !handshake_confirmed_) ||
if (config.requests.empty() ||
(config.delay_stream && !handshake_confirmed_) ||
ev_is_active(&delay_stream_timer_)) {
return;
}
Expand Down
4 changes: 4 additions & 0 deletions deps/ngtcp2/ngtcp2/examples/hq_client_proto_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ ProtoCodec::on_stream_close(int64_t stream_id,
return {};
}

if (auto stream = client_->find_stream(stream_id); stream) {
sendq_.erase(stream);
}

if (!config.quiet) {
std::println(stderr,
"HTTP stream {:#x} closed with error codes (RX:{}, TX:{})",
Expand Down
2 changes: 1 addition & 1 deletion deps/ngtcp2/ngtcp2/examples/hq_client_proto_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class ProtoCodec {
std::expected<void, Error> extend_max_stream_data(int64_t stream_id,
uint64_t max_data);

void early_data_rejected() {}
void early_data_rejected() { sendq_.clear(); }

std::expected<void, Error>
on_stream_close(int64_t stream_id, std::optional<uint64_t> rx_app_error_code,
Expand Down
50 changes: 46 additions & 4 deletions deps/ngtcp2/ngtcp2/examples/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <memory>
#include <fstream>
#include <iomanip>
#include <limits>
#include <utility>

#include <unistd.h>
#include <getopt.h>
Expand Down Expand Up @@ -216,6 +218,11 @@ Stream::open_file(const std::filesystem::path &path) {
close(fd);
} else {
fe.fd = fd;
// A file larger than the address space cannot be mapped.
if (std::cmp_greater(st.st_size, std::numeric_limits<size_t>::max())) {
close(fd);
return std::unexpected{Error::INTEGER_OVERFLOW};
}
fe.len = static_cast<size_t>(st.st_size);
if (fe.len) {
fe.map = mmap(nullptr, fe.len, PROT_READ, MAP_SHARED, fd, 0);
Expand Down Expand Up @@ -321,9 +328,7 @@ void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
}

if (auto rv = h->handle_expiry(); !rv) {
if (rv.error() == Error::CLOSE_WAIT) {
ev_timer_stop(loop, w);
} else {
if (rv.error() != Error::CLOSE_WAIT) {
s->remove(h);
}

Expand Down Expand Up @@ -773,6 +778,7 @@ Handler::init(const Endpoint &ep, const Address &local_addr,
settings.handshake_timeout = config.handshake_timeout;
settings.no_pmtud = config.no_pmtud;
settings.ack_thresh = config.ack_thresh;
settings.write_stream_data_thresh = config.write_stream_data_thresh;
if (config.max_udp_payload_size) {
settings.max_tx_udp_payload_size = config.max_udp_payload_size;
settings.no_tx_udp_payload_size_shaping = 1;
Expand Down Expand Up @@ -1705,7 +1711,9 @@ void Server::on_read(const Endpoint &ep) {
stderr,
"Received packet: local={} remote={} if={} ecn={:#x} {} bytes",
util::straddr(*local_addr), util::straddr(remote_addr),
if_indextoname(local_addr->ifindex, ifname.data()), pi.ecn, datalen);
if_indextoname(local_addr->ifindex, ifname.data()) ? ifname.data()
: "(unknown)",
pi.ecn, datalen);
}

// Packets less than 21 bytes never be a valid QUIC packet.
Expand Down Expand Up @@ -1735,6 +1743,11 @@ void Server::read_pkt(const Endpoint &ep, const Address &local_addr,
NGTCP2_SV_SCIDLEN);
rv) {
case 0:
if ((data[0] & 0x80U) && vc.version == 0) {
// Version Negotiation packet was received.
return;
}

break;
case NGTCP2_ERR_VERSION_NEGOTIATION:
(void)send_version_negotiation(vc.version, {vc.scid, vc.scidlen},
Expand Down Expand Up @@ -2658,6 +2671,15 @@ void print_help() {
to send per an event loop in a single connection. It
defaults to 0, which means it is not limited by the
configuration.
--write-stream-data-thresh=<SIZE>
The threshold for the length of STREAM frame payload
that the local endpoint sends. If there is data more
than this value to send, and the flow control does not
allow sending more than this length, the data is not
sent, waiting for the window update from the remote
endpoint.
Default: )"
<< config.write_stream_data_thresh << R"(
-h, --help Display this help and exit.

---
Expand Down Expand Up @@ -2732,6 +2754,7 @@ int main(int argc, char **argv) {
{"no-gso", no_argument, &flag, 35},
{"show-stat", no_argument, &flag, 36},
{"gso-burst", required_argument, &flag, 37},
{"write-stream-data-thresh", required_argument, &flag, 38},
{},
};

Expand Down Expand Up @@ -3163,6 +3186,25 @@ int main(int argc, char **argv) {

break;
}
case 38: {
// --write-stream-data-thresh
auto n = util::parse_uint_iec(optarg);
if (!n) {
std::println(stderr, "write-stream-data-thresh: invalid argument");
exit(EXIT_FAILURE);
}

if (auto max = std::numeric_limits<size_t>::max(); *n > max) {
std::println(
stderr,
"write-stream-data-thresh: must be less than or equal to {}", max);
exit(EXIT_FAILURE);
}

config.write_stream_data_thresh = static_cast<size_t>(*n);

break;
}
}
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion deps/ngtcp2/ngtcp2/examples/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ enum FileEntryFlag {
};

struct FileEntry {
uint64_t len{};
size_t len{};
void *map{};
int fd{};
uint8_t flags{};
Expand Down
3 changes: 3 additions & 0 deletions deps/ngtcp2/ngtcp2/examples/server_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ struct Config {
// gso_burst is the number of packets to aggregate in GSO. 0 means
// it is not limited by the configuration.
size_t gso_burst{};
// write_stream_data_thresh is the threshold for the length of
// STREAM frame payload that the local endpoint sends.
size_t write_stream_data_thresh{255};
};

struct HTTPHeader {
Expand Down
4 changes: 2 additions & 2 deletions deps/ngtcp2/ngtcp2/examples/sim_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ void test_sim_unistream(void) {

assert_true(rv.has_value());
assert_true(svapp.is_all_bytes_sent());
assert_uint64(link.compute_expected_goodput(link.delay * 2), <=,
svapp.compute_goodput());
assert_lte(link.compute_expected_goodput(link.delay * 2),
svapp.compute_goodput());
}
}

Expand Down
4 changes: 2 additions & 2 deletions deps/ngtcp2/ngtcp2/examples/siphash_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ void test_siphash(void) {
std::array<uint8_t, 15> input;
std::iota(std::ranges::begin(input), std::ranges::end(input), 0);

assert_uint64(0xA129CA6149BE45E5ULL, ==, siphash24(key, input));
assert_eq(0xA129CA6149BE45E5ULL, siphash24(key, input));
}

void test_siphash_vector(void) {
Expand Down Expand Up @@ -91,7 +91,7 @@ void test_siphash_vector(void) {
expect = byteswap(expect);
}

assert_uint64(expect, ==, h);
assert_eq(expect, h);
}
}

Expand Down
2 changes: 1 addition & 1 deletion deps/ngtcp2/ngtcp2/examples/siphash_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

#define MUNIT_ENABLE_ASSERT_ALIASES

#include "munit.h"
#include "munitxx.h"

namespace ngtcp2 {

Expand Down
2 changes: 1 addition & 1 deletion deps/ngtcp2/ngtcp2/examples/tests/ngtcp2test/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def assert_verify_null_handshake(self):
def assert_verify_cert_handshake(self):
c_hs, s_hs = self.norm_exp(
"ServerHello:EncryptedExtensions:CertificateRequest:(Compressed)?Certificate:CertificateVerify:Finished",
"ClientHello:Certificate:CertificateVerify:Finished")
"ClientHello:(Compressed)?Certificate:CertificateVerify:Finished")
self._assert_hs(c_hs, s_hs)


Expand Down
27 changes: 26 additions & 1 deletion deps/ngtcp2/ngtcp2/examples/tests/ngtcp2test/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,31 @@ def to_text(self, indent: int = 0):
f'{ind} certificate_list: \n' + '\n'.join(
[self._enxtry_text(e, indent+4) for e in self._cert_entries])

class CompressedCertificate(HSRecord):

def __init__(self, hsid: int, name: str, data):
super().__init__(hsid=hsid, name=name, data=data)
d = data
d, algorithm = _get_field(d, 2)
self._algorithm = int.from_bytes(bytearray(algorithm), byteorder='big')
d, uncompressed_length = _get_field(d, 3)
self._uncompressed_length = int.from_bytes(bytearray(uncompressed_length), byteorder='big')
d, self._compressed_certificate_message = _get_len_field(d, 3)
assert len(d) == 0

def to_json(self):
jdata = super().to_json()
jdata['algorithm'] = self._algorithm
jdata['uncompressed_length'] = self._uncompressed_length
jdata['compressed_certificate_message'] = binascii.hexlify(self._compressed_certificate_message).decode()
return jdata

def to_text(self, indent: int = 0):
ind = ' ' * (indent + 2)
return super().to_text(indent=indent) + '\n'\
f'{ind} algorithm: {self._algorithm}\n'\
f'{ind} uncompressed_length: {self._uncompressed_length}\n'\
f'{ind} compressed_certificate_message: {binascii.hexlify(self._compressed_certificate_message).decode()}'

class SessionTicket(HSRecord):

Expand Down Expand Up @@ -901,7 +926,7 @@ class HandShake:
(20, 'Finished', HSRecord),
(22, 'CertificateStatus', HSRecord),
(24, 'KeyUpdate', HSRecord),
(25, 'CompressedCertificate', HSRecord),
(25, 'CompressedCertificate', CompressedCertificate),
]
RT_NAME_BY_ID = {}
RT_CLS_BY_ID = {}
Expand Down
10 changes: 7 additions & 3 deletions deps/ngtcp2/ngtcp2/examples/tests/test_04_clientcert.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@ def test_04_02(self, env: Env, server, client):
creqs = [r for r in cr.handshake if r.hsid == 13] # CertificateRequest
assert len(creqs) == 1
creq = creqs[0].to_json()
certs = [r for r in cr.server.handshake if r.hsid == 11] # Certificate
certs = [r for r in cr.server.handshake if r.hsid == 11 or r.hsid == 25] # Certificate or CompressedCertificate
assert len(certs) == 1
crec = certs[0].to_json()
assert len(crec['certificate_list']) == 1
assert creq['context'] == crec['context']
if 'certificate_list' in crec:
cert_list = crec['certificate_list']
assert len(cert_list) == 1
assert creq['context'] == crec['context']
else:
assert 'compressed_certificate_message' in crec
# TODO: check that GET indeed gave a response
Loading
Loading