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 c753466bb394ea4b25b91b8792020e8fc07c8d6c
Author: Masakazu Kitajo <mas...@apache.org>
AuthorDate: Tue Jun 19 17:30:17 2018 +0900

    Add QUICPacketNumberProtector
---
 iocore/net/P_QUICNetVConnection.h         |  3 +-
 iocore/net/QUICNetVConnection.cc          |  1 +
 iocore/net/quic/QUICHandshakeProtocol.cc  | 26 +++++++++
 iocore/net/quic/QUICHandshakeProtocol.h   | 17 ++++++
 iocore/net/quic/QUICPacketReceiveQueue.cc | 90 +++++++++++++++++++++++--------
 iocore/net/quic/QUICPacketReceiveQueue.h  |  5 +-
 6 files changed, 119 insertions(+), 23 deletions(-)

diff --git a/iocore/net/P_QUICNetVConnection.h 
b/iocore/net/P_QUICNetVConnection.h
index e3ba582..543b330 100644
--- a/iocore/net/P_QUICNetVConnection.h
+++ b/iocore/net/P_QUICNetVConnection.h
@@ -246,6 +246,7 @@ private:
   QUICFrameFactory _frame_factory;
   QUICAckFrameCreator _ack_frame_creator;
   QUICPacketRetransmitter _packet_retransmitter;
+  QUICPacketNumberProtector _pn_protector;
   QUICApplicationMap *_application_map = nullptr;
 
   uint32_t _pmtu = 1280;
@@ -266,7 +267,7 @@ private:
   QUICAltConnectionManager *_alt_con_manager        = nullptr;
   QUICPathValidator *_path_validator                = nullptr;
 
-  QUICPacketReceiveQueue _packet_recv_queue = {this->_packet_factory};
+  QUICPacketReceiveQueue _packet_recv_queue = {this->_packet_factory, 
this->_pn_protector};
   CountQueue<QUICPacket> _packet_send_queue;
 
   QUICConnectionErrorUPtr _connection_error  = nullptr;
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index b17d93c..8e39676 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -211,6 +211,7 @@ QUICNetVConnection::start()
   this->_hs_protocol      = this->_handshake_handler->protocol();
   this->_frame_dispatcher = new QUICFrameDispatcher(this);
   this->_packet_factory.set_hs_protocol(this->_hs_protocol);
+  this->_pn_protector.set_hs_protocol(this->_hs_protocol);
 
   // Create frame handlers
   this->_congestion_controller  = new QUICCongestionController(this);
diff --git a/iocore/net/quic/QUICHandshakeProtocol.cc 
b/iocore/net/quic/QUICHandshakeProtocol.cc
index 8d46370..94bf852 100644
--- a/iocore/net/quic/QUICHandshakeProtocol.cc
+++ b/iocore/net/quic/QUICHandshakeProtocol.cc
@@ -78,6 +78,32 @@ QUICPacketProtection::key_phase() const
 }
 
 //
+// QUICPacketNumberProtector
+//
+
+bool
+QUICPacketNumberProtector::protect(uint8_t *protected_pn, uint8_t 
&protected_pn_len, const uint8_t *unprotected_pn,
+                                   uint8_t unprotected_pn_len, const uint8_t 
*sample, QUICKeyPhase phase) const
+{
+  // FIXME HandshakeProtocol shouldn't do this. The logic should be moved from 
there to here.
+  return this->_hs_protocol->encrypt_pn(protected_pn, protected_pn_len, 
unprotected_pn, unprotected_pn_len, sample, phase);
+}
+
+bool
+QUICPacketNumberProtector::unprotect(uint8_t *unprotected_pn, uint8_t 
&unprotected_pn_len, const uint8_t *protected_pn,
+                                     uint8_t protected_pn_len, const uint8_t 
*sample, QUICKeyPhase phase) const
+{
+  // FIXME HandshakeProtocol shouldn't do this. The logic should be moved from 
there to here.
+  return this->_hs_protocol->decrypt_pn(unprotected_pn, unprotected_pn_len, 
protected_pn, protected_pn_len, sample, phase);
+}
+
+void
+QUICPacketNumberProtector::set_hs_protocol(QUICHandshakeProtocol *hs_protocol)
+{
+  this->_hs_protocol = hs_protocol;
+}
+
+//
 // QUICHandshakeProtocol
 //
 QUICHandshakeMsgType
diff --git a/iocore/net/quic/QUICHandshakeProtocol.h 
b/iocore/net/quic/QUICHandshakeProtocol.h
index 0701c4d..aec814c 100644
--- a/iocore/net/quic/QUICHandshakeProtocol.h
+++ b/iocore/net/quic/QUICHandshakeProtocol.h
@@ -26,6 +26,8 @@
 #include "QUICKeyGenerator.h"
 #include "QUICTypes.h"
 
+class QUICHandshakeProtocol;
+
 class QUICPacketProtection
 {
 public:
@@ -43,6 +45,21 @@ private:
   QUICKeyPhase _key_phase                     = QUICKeyPhase::CLEARTEXT;
 };
 
+class QUICPacketNumberProtector
+{
+public:
+  bool protect(uint8_t *protected_pn, uint8_t &protected_pn_len, const uint8_t 
*unprotected_pn, uint8_t unprotected_pn_len,
+               const uint8_t *sample, QUICKeyPhase phase) const;
+  bool unprotect(uint8_t *unprotected_pn, uint8_t &unprotected_pn_len, const 
uint8_t *protected_pn, uint8_t protected_pn_len,
+                 const uint8_t *sample, QUICKeyPhase phase) const;
+
+  // FIXME We don't need QUICHandshakeProtocol here, and should pass 
QUICPacketProtection instead.
+  void set_hs_protocol(QUICHandshakeProtocol *hs_protocol);
+
+private:
+  QUICHandshakeProtocol *_hs_protocol = nullptr;
+};
+
 class QUICHandshakeProtocol
 {
 public:
diff --git a/iocore/net/quic/QUICPacketReceiveQueue.cc 
b/iocore/net/quic/QUICPacketReceiveQueue.cc
index 3a7f435..4fd2ad3 100644
--- a/iocore/net/quic/QUICPacketReceiveQueue.cc
+++ b/iocore/net/quic/QUICPacketReceiveQueue.cc
@@ -24,11 +24,10 @@
 #include "QUICPacketReceiveQueue.h"
 
 #include "QUICIntUtil.h"
+#include "QUICConfig.h"
 
 // FIXME: workaround for coalescing packets
-static constexpr int LONG_HDR_OFFSET_VERSION       = 1;
 static constexpr int LONG_HDR_OFFSET_CONNECTION_ID = 6;
-static constexpr int LONG_HDR_PKT_NUM_LEN          = 4;
 
 static bool
 is_vn(QUICVersion v)
@@ -39,27 +38,22 @@ is_vn(QUICVersion v)
 static size_t
 long_hdr_pkt_len(uint8_t *buf)
 {
-  uint8_t dcil = (buf[5] >> 4);
-  if (dcil) {
-    dcil += 3;
-  }
-  uint8_t scil = (buf[5] & 0x0F);
-  if (scil) {
-    scil += 3;
-  }
-  size_t offset = LONG_HDR_OFFSET_CONNECTION_ID;
-  offset += dcil;
-  offset += scil;
+  uint8_t dcil, scil;
+  QUICPacketLongHeader::dcil(dcil, buf, 6);
+  QUICPacketLongHeader::scil(scil, buf, 6);
 
-  size_t payload_len = QUICIntUtil::read_QUICVariableInt(buf + offset);
-  offset += QUICVariableInt::size(buf + offset);
-  offset += LONG_HDR_PKT_NUM_LEN;
-  offset += payload_len;
+  size_t payload_len_offset = LONG_HDR_OFFSET_CONNECTION_ID + dcil + scil;
 
-  return offset;
+  size_t payload_len;
+  uint8_t payload_len_field_len;
+  QUICPacketLongHeader::payload_length(payload_len, &payload_len_field_len, 
buf, payload_len_offset + 4);
+  return payload_len_offset + payload_len_field_len + 
QUICTypeUtil::read_QUICPacketNumberLen(buf) + payload_len;
 }
 
-QUICPacketReceiveQueue::QUICPacketReceiveQueue(QUICPacketFactory 
&packet_factory) : _packet_factory(packet_factory) {}
+QUICPacketReceiveQueue::QUICPacketReceiveQueue(QUICPacketFactory 
&packet_factory, QUICPacketNumberProtector &pn_protector)
+  : _packet_factory(packet_factory), _pn_protector(pn_protector)
+{
+}
 
 void
 QUICPacketReceiveQueue::enqueue(UDPPacket *packet)
@@ -103,7 +97,8 @@ QUICPacketReceiveQueue::dequeue(QUICPacketCreationResult 
&result)
     size_t remaining_len = this->_payload_len - this->_offset;
 
     if (QUICInvariants::is_long_header(buf)) {
-      QUICVersion version = QUICTypeUtil::read_QUICVersion(buf + 
LONG_HDR_OFFSET_VERSION);
+      QUICVersion version;
+      QUICPacketLongHeader::version(version, buf, remaining_len);
       if (is_vn(version)) {
         pkt_len = remaining_len;
       } else if (!QUICTypeUtil::is_supported_version(version)) {
@@ -142,7 +137,11 @@ QUICPacketReceiveQueue::dequeue(QUICPacketCreationResult 
&result)
     this->_offset      = 0;
   }
 
-  quic_packet = this->_packet_factory.create(this->_from, std::move(pkt), 
pkt_len, this->_largest_received_packet_number, result);
+  if (this->_unprotect_packet_number(pkt.get(), pkt_len)) {
+    quic_packet = this->_packet_factory.create(this->_from, std::move(pkt), 
pkt_len, this->_largest_received_packet_number, result);
+  } else {
+    result = QUICPacketCreationResult::FAILED;
+  }
 
   if (udp_packet) {
     udp_packet->free();
@@ -179,3 +178,52 @@ 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 6349d26..230fc8a 100644
--- a/iocore/net/quic/QUICPacketReceiveQueue.h
+++ b/iocore/net/quic/QUICPacketReceiveQueue.h
@@ -31,7 +31,7 @@
 class QUICPacketReceiveQueue
 {
 public:
-  QUICPacketReceiveQueue(QUICPacketFactory &packet_factory);
+  QUICPacketReceiveQueue(QUICPacketFactory &packet_factory, 
QUICPacketNumberProtector &pn_protector);
 
   void enqueue(UDPPacket *packet);
   QUICPacketUPtr dequeue(QUICPacketCreationResult &result);
@@ -41,10 +41,13 @@ public:
 private:
   CountQueue<UDPPacket> _queue;
   QUICPacketFactory &_packet_factory;
+  QUICPacketNumberProtector &_pn_protector;
   QUICPacketNumber _largest_received_packet_number = 0;
   // FIXME: workaround code for coalescing packets
   ats_unique_buf _payload = {nullptr, [](void *p) { ats_free(p); }};
   size_t _payload_len     = 0;
   size_t _offset          = 0;
   IpEndpoint _from;
+
+  bool _unprotect_packet_number(uint8_t *packet, size_t packet_len);
 };

Reply via email to