diff --git a/src/shrpx_http3_upstream.cc b/src/shrpx_http3_upstream.cc index 29274c73..1c15f57b 100644 --- a/src/shrpx_http3_upstream.cc +++ b/src/shrpx_http3_upstream.cc @@ -479,7 +479,7 @@ int Http3Upstream::handshake_completed() { return -1; } - std::array token; + std::array token; size_t tokenlen; auto path = ngtcp2_conn_get_path(conn_); @@ -494,6 +494,10 @@ int Http3Upstream::handshake_completed() { return 0; } + assert(tokenlen == NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN); + + token[tokenlen++] = qkm.id; + auto rv = ngtcp2_conn_submit_new_token(conn_, token.data(), tokenlen); if (rv != 0) { ULOG(ERROR, this) << "ngtcp2_conn_submit_new_token: " diff --git a/src/shrpx_quic.cc b/src/shrpx_quic.cc index d49c1744..ffc2fec9 100644 --- a/src/shrpx_quic.cc +++ b/src/shrpx_quic.cc @@ -358,10 +358,9 @@ int generate_quic_connection_id_encryption_key(uint8_t *key, size_t keylen, } const QUICKeyingMaterial * -select_quic_keying_material(const QUICKeyingMaterials &qkms, - const uint8_t *cid) { +select_quic_keying_material(const QUICKeyingMaterials &qkms, uint8_t km_id) { for (auto &qkm : qkms.keying_materials) { - if (((*cid) & 0xc0) == qkm.id) { + if (km_id == qkm.id) { return &qkm; } } diff --git a/src/shrpx_quic.h b/src/shrpx_quic.h index a1533a60..b2f60879 100644 --- a/src/shrpx_quic.h +++ b/src/shrpx_quic.h @@ -76,6 +76,7 @@ constexpr size_t SHRPX_QUIC_STATELESS_RESET_BURST = 100; constexpr size_t SHRPX_QUIC_SECRET_RESERVEDLEN = 4; constexpr size_t SHRPX_QUIC_SECRETLEN = 32; constexpr size_t SHRPX_QUIC_SALTLEN = 32; +constexpr uint8_t SHRPX_QUIC_DCID_KM_ID_MASK = 0xc0; ngtcp2_tstamp quic_timestamp(); @@ -130,8 +131,7 @@ int generate_quic_connection_id_encryption_key(uint8_t *key, size_t keylen, size_t saltlen); const QUICKeyingMaterial * -select_quic_keying_material(const QUICKeyingMaterials &qkms, - const uint8_t *cid); +select_quic_keying_material(const QUICKeyingMaterials &qkms, uint8_t km_id); } // namespace shrpx diff --git a/src/shrpx_quic_connection_handler.cc b/src/shrpx_quic_connection_handler.cc index e7f18900..12ddca85 100644 --- a/src/shrpx_quic_connection_handler.cc +++ b/src/shrpx_quic_connection_handler.cc @@ -128,7 +128,8 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, const QUICKeyingMaterial *qkm = nullptr; if (vc.dcidlen == SHRPX_QUIC_SCIDLEN) { - qkm = select_quic_keying_material(*qkms.get(), vc.dcid); + qkm = select_quic_keying_material( + *qkms.get(), vc.dcid[0] & SHRPX_QUIC_DCID_KM_ID_MASK); if (decrypt_quic_connection_id(decrypted_dcid.data(), vc.dcid + SHRPX_QUIC_CID_PREFIX_OFFSET, @@ -221,7 +222,8 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, return 0; } - auto qkm = select_quic_keying_material(*qkms.get(), vc.dcid); + auto qkm = select_quic_keying_material( + *qkms.get(), vc.dcid[0] & SHRPX_QUIC_DCID_KM_ID_MASK); if (verify_retry_token(odcid, hd.token.base, hd.token.len, hd.version, hd.dcid, &remote_addr.su.sa, remote_addr.len, @@ -257,12 +259,26 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, return 0; } - // Regarding the QUIC secret that encrypted this token, DCID - // is a client chosen one, and we have no information embedded - // in a token. Just use the first QUIC secret. - auto qkm = &qkms->keying_materials.front(); + if (hd.token.len != NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN + 1) { + if (LOG_ENABLED(INFO)) { + LOG(INFO) << "Failed to validate token from remote=" + << util::to_numeric_addr(&remote_addr); + } - if (verify_token(hd.token.base, hd.token.len, &remote_addr.su.sa, + if (quicconf.upstream.require_token) { + send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, + vc.scidlen, remote_addr, local_addr, datalen * 3); + + return 0; + } + + break; + } + + auto qkm = select_quic_keying_material( + *qkms.get(), hd.token.base[NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN]); + + if (verify_token(hd.token.base, hd.token.len - 1, &remote_addr.su.sa, remote_addr.len, qkm->secret.data(), qkm->secret.size()) != 0) { if (LOG_ENABLED(INFO)) {