You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2018/06/21 02:09:12 UTC
[trafficserver] 03/04: Protect sending packet numbers
This is an automated email from the ASF dual-hosted git repository.
maskit pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 6751e97d47d4bef227c35ba206ae4466292b1cdc
Author: Masakazu Kitajo <ma...@apache.org>
AuthorDate: Thu Jun 21 11:07:08 2018 +0900
Protect sending packet numbers
---
iocore/net/P_QUICPacketHandler.h | 10 +--
iocore/net/QUICNetVConnection.cc | 6 +-
iocore/net/QUICPacketHandler.cc | 20 +++---
iocore/net/quic/QUICPacket.cc | 100 ++++++++++++++++++++++++++++++
iocore/net/quic/QUICPacket.h | 5 ++
iocore/net/quic/QUICPacketReceiveQueue.cc | 51 +--------------
iocore/net/quic/QUICPacketReceiveQueue.h | 2 -
7 files changed, 128 insertions(+), 66 deletions(-)
diff --git a/iocore/net/P_QUICPacketHandler.h b/iocore/net/P_QUICPacketHandler.h
index 3e982bc..77fe364 100644
--- a/iocore/net/P_QUICPacketHandler.h
+++ b/iocore/net/P_QUICPacketHandler.h
@@ -32,6 +32,7 @@
class QUICClosedConCollector;
class QUICNetVConnection;
class QUICPacket;
+class QUICPacketNumberProtector;
class QUICPacketHandler
{
@@ -39,11 +40,12 @@ public:
QUICPacketHandler();
~QUICPacketHandler();
- virtual void send_packet(const QUICPacket &packet, QUICNetVConnection *vc) = 0;
+ virtual void send_packet(const QUICPacket &packet, QUICNetVConnection *vc, QUICPacketNumberProtector &pn_protector) = 0;
virtual void close_conenction(QUICNetVConnection *conn);
protected:
- static void _send_packet(Continuation *c, const QUICPacket &packet, UDPConnection *udp_con, IpEndpoint &addr, uint32_t pmtu);
+ static void _send_packet(Continuation *c, const QUICPacket &packet, UDPConnection *udp_con, IpEndpoint &addr, uint32_t pmtu,
+ QUICPacketNumberProtector *pn_protector);
Event *_collector_event = nullptr;
QUICClosedConCollector *_closed_con_collector = nullptr;
@@ -68,7 +70,7 @@ public:
void init_accept(EThread *t) override;
// QUICPacketHandler
- virtual void send_packet(const QUICPacket &packet, QUICNetVConnection *vc) override;
+ virtual void send_packet(const QUICPacket &packet, QUICNetVConnection *vc, QUICPacketNumberProtector &pn_protector) override;
private:
void _recv_packet(int event, UDPPacket *udp_packet) override;
@@ -90,7 +92,7 @@ public:
int event_handler(int event, Event *data);
// QUICPacketHandler
- virtual void send_packet(const QUICPacket &packet, QUICNetVConnection *vc) override;
+ virtual void send_packet(const QUICPacket &packet, QUICNetVConnection *vc, QUICPacketNumberProtector &pn_protector) override;
private:
void _recv_packet(int event, UDPPacket *udp_packet) override;
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index e472756..a9c9d20 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -1077,7 +1077,7 @@ QUICNetVConnection::_state_common_send_packet()
break;
}
- this->_packet_handler->send_packet(*packet, this);
+ this->_packet_handler->send_packet(*packet, this, this->_pn_protector);
if (packet->type() == QUICPacketType::HANDSHAKE) {
++this->_handshake_packets_sent;
}
@@ -1116,7 +1116,7 @@ QUICNetVConnection::_state_handshake_send_retry_packet()
}
QUICPacketUPtr packet = this->_build_packet(std::move(buf), len, retransmittable, QUICPacketType::RETRY);
- this->_packet_handler->send_packet(*packet, this);
+ this->_packet_handler->send_packet(*packet, this, this->_pn_protector);
this->_loss_detector->on_packet_sent(std::move(packet));
QUIC_INCREMENT_DYN_STAT_EX(QUICStats::total_packets_sent_stat, 1);
@@ -1137,7 +1137,7 @@ QUICNetVConnection::_state_closing_send_packet()
// that an endpoint maintains for a closing connection, endpoints MAY
// send the exact same packet.
if (this->_the_final_packet) {
- this->_packet_handler->send_packet(*this->_the_final_packet, this);
+ this->_packet_handler->send_packet(*this->_the_final_packet, this, this->_pn_protector);
}
return QUICErrorUPtr(new QUICNoError());
}
diff --git a/iocore/net/QUICPacketHandler.cc b/iocore/net/QUICPacketHandler.cc
index ab2a573..7e6a58e 100644
--- a/iocore/net/QUICPacketHandler.cc
+++ b/iocore/net/QUICPacketHandler.cc
@@ -70,7 +70,8 @@ QUICPacketHandler::close_conenction(QUICNetVConnection *conn)
}
void
-QUICPacketHandler::_send_packet(Continuation *c, const QUICPacket &packet, UDPConnection *udp_con, IpEndpoint &addr, uint32_t pmtu)
+QUICPacketHandler::_send_packet(Continuation *c, const QUICPacket &packet, UDPConnection *udp_con, IpEndpoint &addr, uint32_t pmtu,
+ QUICPacketNumberProtector *pn_protector)
{
size_t udp_len;
Ptr<IOBufferBlock> udp_payload(new_IOBufferBlock());
@@ -78,6 +79,10 @@ QUICPacketHandler::_send_packet(Continuation *c, const QUICPacket &packet, UDPCo
packet.store(reinterpret_cast<uint8_t *>(udp_payload->end()), &udp_len);
udp_payload->fill(udp_len);
+ if (pn_protector) {
+ QUICPacket::protect_packet_number(reinterpret_cast<uint8_t *>(udp_payload->start()), udp_len, pn_protector);
+ }
+
UDPPacket *udp_packet = new_UDPPacket(addr, 0, udp_payload);
if (is_debug_tag_set(tag)) {
@@ -216,7 +221,7 @@ QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet)
QUICDebugDS(scid, dcid, "Unsupported version: 0x%x", v);
QUICPacketUPtr vn = QUICPacketFactory::create_version_negotiation_packet(scid, dcid);
- this->_send_packet(this, *vn, udp_packet->getConnection(), udp_packet->from, 1200);
+ this->_send_packet(this, *vn, udp_packet->getConnection(), udp_packet->from, 1200, nullptr);
udp_packet->free();
return;
}
@@ -247,7 +252,7 @@ QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet)
token.generate(dcid, params->server_id());
}
auto packet = QUICPacketFactory::create_stateless_reset_packet(dcid, token);
- this->_send_packet(this, *packet, udp_packet->getConnection(), udp_packet->from, 1200);
+ this->_send_packet(this, *packet, udp_packet->getConnection(), udp_packet->from, 1200, nullptr);
udp_packet->free();
return;
}
@@ -297,9 +302,9 @@ QUICPacketHandlerIn::_recv_packet(int event, UDPPacket *udp_packet)
// TODO: Should be called via eventProcessor?
void
-QUICPacketHandlerIn::send_packet(const QUICPacket &packet, QUICNetVConnection *vc)
+QUICPacketHandlerIn::send_packet(const QUICPacket &packet, QUICNetVConnection *vc, QUICPacketNumberProtector &pn_protector)
{
- this->_send_packet(this, packet, vc->get_udp_con(), vc->con.addr, vc->pmtu());
+ this->_send_packet(this, packet, vc->get_udp_con(), vc->con.addr, vc->pmtu(), &pn_protector);
}
//
@@ -342,9 +347,10 @@ QUICPacketHandlerOut::event_handler(int event, Event *data)
}
void
-QUICPacketHandlerOut::send_packet(const QUICPacket &packet, QUICNetVConnection *vc)
+QUICPacketHandlerOut::send_packet(const QUICPacket &packet, QUICNetVConnection *vc, QUICPacketNumberProtector &pn_protector)
{
- this->_send_packet(this, packet, vc->get_udp_con(), vc->con.addr, vc->pmtu());
+ // TODO Pass QUICPacketNumberProtector
+ this->_send_packet(this, packet, vc->get_udp_con(), vc->con.addr, vc->pmtu(), nullptr);
}
void
diff --git a/iocore/net/quic/QUICPacket.cc b/iocore/net/quic/QUICPacket.cc
index d9cb9d0..a28a3f5 100644
--- a/iocore/net/quic/QUICPacket.cc
+++ b/iocore/net/quic/QUICPacket.cc
@@ -258,6 +258,20 @@ QUICPacketLongHeader::length(size_t &length, uint8_t *field_len, const uint8_t *
return true;
}
+bool
+QUICPacketLongHeader::packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len)
+{
+ uint8_t dcil, scil;
+ size_t length;
+ uint8_t length_field_len;
+ if (!QUICPacketLongHeader::dcil(dcil, packet, packet_len) || !QUICPacketLongHeader::scil(scil, packet, packet_len) ||
+ !QUICPacketLongHeader::length(length, &length_field_len, packet, packet_len)) {
+ return false;
+ }
+ pn_offset = 6 + dcil + scil + length_field_len;
+ return true;
+}
+
QUICConnectionId
QUICPacketLongHeader::destination_cid() const
{
@@ -530,6 +544,14 @@ QUICPacketShortHeader::key_phase(QUICKeyPhase &phase, const uint8_t *packet, siz
return true;
}
+bool
+QUICPacketShortHeader::packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len)
+{
+ int connection_id_len = QUICConfigParams::scid_len();
+ pn_offset = 1 + connection_id_len;
+ return true;
+}
+
/**
* Header Length (doesn't include payload length)
*/
@@ -733,6 +755,84 @@ QUICPacket::decode_packet_number(QUICPacketNumber &dst, QUICPacketNumber src, si
return true;
}
+bool
+QUICPacket::protect_packet_number(uint8_t *packet, size_t packet_len, QUICPacketNumberProtector *pn_protector)
+{
+ size_t pn_offset = 0;
+ uint8_t pn_len = 4;
+ size_t sample_offset = 0;
+ uint8_t sample_len = 0;
+ constexpr int aead_expansion = 16; // Currently, AEAD expansion (which is probably AEAD tag) length is always 16
+ QUICKeyPhase phase;
+
+ if (QUICInvariants::is_long_header(packet)) {
+ QUICPacketType type;
+ QUICPacketLongHeader::type(type, packet, packet_len);
+ switch (type) {
+ case QUICPacketType::ZERO_RTT_PROTECTED:
+ phase = QUICKeyPhase::ZERORTT;
+ break;
+ default:
+ phase = QUICKeyPhase::CLEARTEXT;
+ break;
+ }
+ QUICPacketLongHeader::packet_number_offset(pn_offset, packet, packet_len);
+ } else {
+ QUICPacketShortHeader::key_phase(phase, packet, packet_len);
+ QUICPacketShortHeader::packet_number_offset(pn_offset, packet, packet_len);
+ }
+ sample_offset = std::min(pn_offset + 4, packet_len - aead_expansion);
+ sample_len = 16; // On draft-12, the length is always 16 (See 5.6.1 and 5.6.2)
+
+ uint8_t protected_pn[4] = {0};
+ uint8_t protected_pn_len = 0;
+ pn_len = QUICTypeUtil::read_QUICPacketNumberLen(packet + pn_offset);
+ if (!pn_protector->protect(protected_pn, protected_pn_len, packet + pn_offset, pn_len, packet + sample_offset, phase)) {
+ return false;
+ }
+ memcpy(packet + pn_offset, protected_pn, pn_len);
+ return true;
+}
+
+bool
+QUICPacket::unprotect_packet_number(uint8_t *packet, size_t packet_len, QUICPacketNumberProtector *pn_protector)
+{
+ size_t pn_offset = 0;
+ uint8_t pn_len = 4;
+ size_t sample_offset = 0;
+ uint8_t sample_len = 0;
+ constexpr int aead_expansion = 16; // Currently, AEAD expansion (which is probably AEAD tag) length is always 16
+ QUICKeyPhase phase;
+
+ if (QUICInvariants::is_long_header(packet)) {
+ QUICPacketType type;
+ QUICPacketLongHeader::type(type, packet, packet_len);
+ switch (type) {
+ case QUICPacketType::ZERO_RTT_PROTECTED:
+ phase = QUICKeyPhase::ZERORTT;
+ break;
+ default:
+ phase = QUICKeyPhase::CLEARTEXT;
+ break;
+ }
+ QUICPacketLongHeader::packet_number_offset(pn_offset, packet, packet_len);
+ } else {
+ QUICPacketShortHeader::key_phase(phase, packet, packet_len);
+ QUICPacketShortHeader::packet_number_offset(pn_offset, packet, packet_len);
+ }
+ sample_offset = std::min(pn_offset + 4, packet_len - aead_expansion);
+ sample_len = 16; // On draft-12, the length is always 16 (See 5.6.1 and 5.6.2)
+
+ uint8_t unprotected_pn[4] = {0};
+ uint8_t unprotected_pn_len = 0;
+ if (!pn_protector->unprotect(unprotected_pn, unprotected_pn_len, packet + pn_offset, pn_len, packet + sample_offset, phase)) {
+ return false;
+ }
+ unprotected_pn_len = QUICTypeUtil::read_QUICPacketNumberLen(unprotected_pn);
+ memcpy(packet + pn_offset, unprotected_pn, unprotected_pn_len);
+ return true;
+}
+
//
// QUICPacketFactory
//
diff --git a/iocore/net/quic/QUICPacket.h b/iocore/net/quic/QUICPacket.h
index 3ce9bc8..4067fda 100644
--- a/iocore/net/quic/QUICPacket.h
+++ b/iocore/net/quic/QUICPacket.h
@@ -201,6 +201,7 @@ public:
*/
static bool scil(uint8_t &scil, const uint8_t *packet, size_t packet_len);
static bool length(size_t &length, uint8_t *field_len, const uint8_t *packet, size_t packet_len);
+ static bool packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len);
private:
QUICPacketNumber _packet_number;
@@ -237,6 +238,7 @@ public:
void store(uint8_t *buf, size_t *len) const;
static bool key_phase(QUICKeyPhase &key_phase, const uint8_t *packet, size_t packet_len);
+ static bool packet_number_offset(size_t &pn_offset, const uint8_t *packet, size_t packet_len);
private:
int _packet_number_len;
@@ -328,6 +330,9 @@ public:
static bool encode_packet_number(QUICPacketNumber &dst, QUICPacketNumber src, size_t len);
static bool decode_packet_number(QUICPacketNumber &dst, QUICPacketNumber src, size_t len, QUICPacketNumber largest_acked);
+ static bool protect_packet_number(uint8_t *packet, size_t packet_len, QUICPacketNumberProtector *pn_protector);
+ static bool unprotect_packet_number(uint8_t *packet, size_t packet_len, QUICPacketNumberProtector *pn_protector);
+
LINK(QUICPacket, link);
private:
diff --git a/iocore/net/quic/QUICPacketReceiveQueue.cc b/iocore/net/quic/QUICPacketReceiveQueue.cc
index bfd6c5f..fcb3184 100644
--- a/iocore/net/quic/QUICPacketReceiveQueue.cc
+++ b/iocore/net/quic/QUICPacketReceiveQueue.cc
@@ -138,7 +138,7 @@ QUICPacketReceiveQueue::dequeue(QUICPacketCreationResult &result)
this->_offset = 0;
}
- if (this->_unprotect_packet_number(pkt.get(), pkt_len)) {
+ if (QUICPacket::unprotect_packet_number(pkt.get(), pkt_len, &this->_pn_protector)) {
quic_packet = this->_packet_factory.create(this->_from, std::move(pkt), pkt_len, this->_largest_received_packet_number, result);
} else {
result = QUICPacketCreationResult::FAILED;
@@ -179,52 +179,3 @@ QUICPacketReceiveQueue::reset()
{
this->_largest_received_packet_number = 0;
}
-
-bool
-QUICPacketReceiveQueue::_unprotect_packet_number(uint8_t *packet, size_t packet_len)
-{
- size_t pn_offset = 0;
- uint8_t pn_len = 4;
- size_t sample_offset = 0;
- uint8_t sample_len = 0;
- constexpr int aead_expansion = 16; // Currently, AEAD expansion (which is probably AEAD tag) length is always 16
- int connection_id_len = QUICConfigParams::scid_len();
- QUICKeyPhase phase;
-
- if (QUICInvariants::is_long_header(packet)) {
- QUICPacketType type;
- QUICPacketLongHeader::type(type, packet, packet_len);
- switch (type) {
- case QUICPacketType::ZERO_RTT_PROTECTED:
- phase = QUICKeyPhase::ZERORTT;
- break;
- default:
- phase = QUICKeyPhase::CLEARTEXT;
- break;
- }
-
- uint8_t dcil, scil;
- size_t payload_length;
- uint8_t payload_length_field_len;
- if (!QUICPacketLongHeader::dcil(dcil, packet, packet_len) || !QUICPacketLongHeader::scil(scil, packet, packet_len) ||
- !QUICPacketLongHeader::payload_length(payload_length, &payload_length_field_len, packet, packet_len)) {
- return false;
- }
- pn_offset = 6 + dcil + scil + payload_length_field_len;
- } else {
- QUICPacketShortHeader::key_phase(phase, packet, packet_len);
- pn_offset = 1 + connection_id_len;
- }
- sample_offset = std::min(pn_offset + 4, packet_len - aead_expansion);
- sample_len = 16; // On draft-12, the length is always 16 (See 5.6.1 and 5.6.2)
-
- uint8_t unprotected_pn[4] = {0};
- uint8_t unprotected_pn_len = 0;
- if (!this->_pn_protector.unprotect(unprotected_pn, unprotected_pn_len, packet + pn_offset, pn_len, packet + sample_offset,
- phase)) {
- return false;
- }
- unprotected_pn_len = QUICTypeUtil::read_QUICPacketNumberLen(unprotected_pn);
- memcpy(packet + pn_offset, unprotected_pn, unprotected_pn_len);
- return true;
-}
diff --git a/iocore/net/quic/QUICPacketReceiveQueue.h b/iocore/net/quic/QUICPacketReceiveQueue.h
index 230fc8a..9f9a3b8 100644
--- a/iocore/net/quic/QUICPacketReceiveQueue.h
+++ b/iocore/net/quic/QUICPacketReceiveQueue.h
@@ -48,6 +48,4 @@ private:
size_t _payload_len = 0;
size_t _offset = 0;
IpEndpoint _from;
-
- bool _unprotect_packet_number(uint8_t *packet, size_t packet_len);
};