Skip to content

Commit

Permalink
Update RETRY packet
Browse files Browse the repository at this point in the history
  • Loading branch information
maskit committed Jan 29, 2020
1 parent bf08848 commit bc33fc3
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 84 deletions.
9 changes: 9 additions & 0 deletions iocore/net/QUICNetVConnection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,15 @@ QUICNetVConnection::_state_handshake_process_retry_packet(const QUICRetryPacketR
return nullptr;
}

// Check Integrity Tag
if (!packet.has_valid_tag(this->_original_quic_connection_id)) {
// Discard the packet
QUICConDebug("Ignore RETRY packet - integrity tag is not valid");
return nullptr;
} else {
QUICConDebug("Integrity tag is valid");
}

// TODO: move packet->payload to _av_token
this->_av_token_len = packet.token().length();
this->_av_token = ats_unique_malloc(this->_av_token_len);
Expand Down
12 changes: 7 additions & 5 deletions iocore/net/QUICPacketHandler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -394,10 +394,11 @@ QUICPacketHandlerIn::_stateless_retry(const uint8_t *buf, uint64_t buf_len, UDPC
QUICRetryToken token(from, dcid);
QUICConnectionId local_cid;
local_cid.randomize();
QUICPacketUPtr retry_packet = QUICPacketFactory::create_retry_packet(scid, local_cid, dcid, token);
QUICPacketUPtr retry_packet = QUICPacketFactory::create_retry_packet(scid, local_cid, token);

QUICDebug("[TX] %s packet ODCID=%" PRIx64 " token_length=%u", QUICDebugNames::packet_type(retry_packet->type()),
static_cast<uint64_t>(static_cast<const QUICRetryPacket &>(*retry_packet).original_dcid()), token.length());
QUICDebug("[TX] %s packet ODCID=%" PRIx64 " token_length=%u token=%02x%02x%02x%02x...",
QUICDebugNames::packet_type(retry_packet->type()), static_cast<uint64_t>(token.original_dcid()), token.length(),
token.buf()[0], token.buf()[1], token.buf()[2], token.buf()[3]);
this->_send_packet(*retry_packet, connection, from, 1200, nullptr, 0);

return -2;
Expand All @@ -411,8 +412,9 @@ QUICPacketHandlerIn::_stateless_retry(const uint8_t *buf, uint64_t buf_len, UDPC
QUICDebug("Retry Token is valid. ODCID=%" PRIx64, static_cast<uint64_t>(*original_cid));
return 0;
} else {
QUICDebug("Retry token is invalid: ODCID=%" PRIx64 "token_length=%u", static_cast<uint64_t>(token.original_dcid()),
token.length());
QUICDebug("Retry token is invalid: ODCID=%" PRIx64 "token_length=%u token=%02x%02x%02x%02x...",
static_cast<uint64_t>(token.original_dcid()), token.length(), token.buf()[0], token.buf()[1], token.buf()[2],
token.buf()[3]);
this->_send_invalid_token_error(buf, buf_len, connection, from);
return -3;
}
Expand Down
1 change: 1 addition & 0 deletions iocore/net/quic/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ libquic_a_SOURCES = \
QUICPathManager.cc \
QUICPathValidator.cc \
QUICPinger.cc \
QUICRetryIntegrityTag.cc \
QUICFrameGenerator.cc \
QUICFrameRetransmitter.cc \
QUICAddrVerifyState.cc \
Expand Down
74 changes: 30 additions & 44 deletions iocore/net/quic/QUICPacket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "QUICIntUtil.h"
#include "QUICDebugNames.h"
#include "QUICRetryIntegrityTag.h"

using namespace std::literals;
static constexpr uint64_t aead_tag_len = 16;
Expand Down Expand Up @@ -1626,9 +1627,8 @@ QUICHandshakePacketR::attach_payload(Ptr<IOBufferBlock> payload, bool unprotecte
//
// QUICRetryPacket
//
QUICRetryPacket::QUICRetryPacket(QUICVersion version, QUICConnectionId dcid, QUICConnectionId scid, QUICConnectionId ocid,
QUICRetryToken &token)
: QUICLongHeaderPacket(version, dcid, scid, false, false, false), _ocid(ocid), _token(token)
QUICRetryPacket::QUICRetryPacket(QUICVersion version, QUICConnectionId dcid, QUICConnectionId scid, QUICRetryToken &token)
: QUICLongHeaderPacket(version, dcid, scid, false, false, false), _token(token)
{
}

Expand Down Expand Up @@ -1681,39 +1681,22 @@ QUICRetryPacket::payload_block() const
Ptr<IOBufferBlock> block;
uint8_t *buf;
size_t written_len = 0;
size_t n;

block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
block->alloc(iobuffer_size_to_index(QUICConnectionId::MAX_LENGTH + this->_token.length()));
block->alloc(iobuffer_size_to_index(QUICConnectionId::MAX_LENGTH + this->_token.length() + QUICRetryIntegrityTag::LEN));
buf = reinterpret_cast<uint8_t *>(block->start());

// Original Destination Connection ID
if (this->_ocid != QUICConnectionId::ZERO()) {
// Len
buf[written_len] = this->_ocid.length();
written_len += 1;

// ID
QUICTypeUtil::write_QUICConnectionId(this->_ocid, buf + written_len, &n);
written_len += n;
} else {
buf[written_len] = 0;
written_len += 1;
}

// Retry Token
memcpy(buf + written_len, this->_token.buf(), this->_token.length());
written_len += this->_token.length();

block->fill(written_len);

return block;
}
// Retry Integrity Tag
QUICRetryIntegrityTag::compute(buf + written_len, this->_token.original_dcid(), this->header_block(), block);
written_len += QUICRetryIntegrityTag::LEN;
block->fill(QUICRetryIntegrityTag::LEN);

QUICConnectionId
QUICRetryPacket::original_dcid() const
{
return this->_ocid;
return block;
}

const QUICRetryToken &
Expand Down Expand Up @@ -1756,20 +1739,20 @@ QUICRetryPacketR::QUICRetryPacketR(UDPConnection *udp_con, IpEndpoint from, IpEn
this->_scid = {raw_buf + offset, scil};
offset += scil;

// Original Destination Connection ID
uint8_t odcil = raw_buf[offset];
offset += 1;
this->_odcid = {raw_buf + offset, odcil};
offset += odcil;

// Retry Token field
this->_token = new QUICRetryToken(raw_buf + offset, len - offset);
this->_token = new QUICRetryToken(raw_buf + offset, len - offset - QUICRetryIntegrityTag::LEN);
offset += this->_token->length();

this->_header_block = concatinated_block->clone();
this->_header_block->_end = this->_header_block->_start + offset;
this->_header_block->next = nullptr;
this->_payload_block = concatinated_block->clone();
this->_payload_block->_start = this->_payload_block->_start + offset;
// Retry Integrity Tag
memcpy(this->_integrity_tag, raw_buf + offset, QUICRetryIntegrityTag::LEN);

this->_header_block = concatinated_block->clone();
this->_header_block->_end = this->_header_block->_start + offset;
this->_header_block->next = nullptr;
this->_payload_block = concatinated_block->clone();
this->_payload_block->_start = this->_payload_block->_start + offset;
this->_payload_block_without_tag = this->_payload_block->clone();
this->_payload_block_without_tag->_end = this->_payload_block_without_tag->_end - QUICRetryIntegrityTag::LEN;
}

QUICRetryPacketR::~QUICRetryPacketR()
Expand Down Expand Up @@ -1801,14 +1784,17 @@ QUICRetryPacketR::packet_number() const
return this->_packet_number;
}

QUICConnectionId
QUICRetryPacketR::original_dcid() const
{
return this->_odcid;
}

const QUICAddressValidationToken &
QUICRetryPacketR::token() const
{
return *(this->_token);
}

bool
QUICRetryPacketR::has_valid_tag(QUICConnectionId &odcid) const
{
uint8_t tag_computed[QUICRetryIntegrityTag::LEN];
QUICRetryIntegrityTag::compute(tag_computed, odcid, this->_header_block, this->_payload_block_without_tag);

return memcmp(this->_integrity_tag, tag_computed, QUICRetryIntegrityTag::LEN) == 0;
}
13 changes: 8 additions & 5 deletions iocore/net/quic/QUICPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "I_IOBuffer.h"

#include "QUICTypes.h"
#include "QUICRetryIntegrityTag.h"

#define QUIC_FIELD_OFFSET_CONNECTION_ID 1
#define QUIC_FIELD_OFFSET_PACKET_NUMBER 4
Expand Down Expand Up @@ -505,7 +506,7 @@ class QUICRetryPacket : public QUICLongHeaderPacket
/**
* For sending packet
*/
QUICRetryPacket(QUICVersion version, QUICConnectionId dcid, QUICConnectionId scid, QUICConnectionId ocid, QUICRetryToken &token);
QUICRetryPacket(QUICVersion version, QUICConnectionId dcid, QUICConnectionId scid, QUICRetryToken &token);

QUICPacketType type() const override;
QUICPacketNumber packet_number() const override;
Expand All @@ -514,12 +515,13 @@ class QUICRetryPacket : public QUICLongHeaderPacket
Ptr<IOBufferBlock> header_block() const override;
Ptr<IOBufferBlock> payload_block() const override;

QUICConnectionId original_dcid() const;
const QUICRetryToken &token() const;

private:
QUICConnectionId _ocid;
QUICRetryToken _token;

bool _compute_retry_integrity_tag(uint8_t *out, QUICConnectionId odcid, Ptr<IOBufferBlock> header,
Ptr<IOBufferBlock> payload) const;
};

class QUICRetryPacketR : public QUICLongHeaderPacketR
Expand All @@ -537,11 +539,12 @@ class QUICRetryPacketR : public QUICLongHeaderPacketR
QUICPacketType type() const override;
QUICPacketNumber packet_number() const override;

QUICConnectionId original_dcid() const;
const QUICAddressValidationToken &token() const;
bool has_valid_tag(QUICConnectionId &odcid) const;

private:
QUICPacketNumber _packet_number;
QUICConnectionId _odcid;
QUICAddressValidationToken *_token = nullptr;
uint8_t _integrity_tag[QUICRetryIntegrityTag::LEN];
Ptr<IOBufferBlock> _payload_block_without_tag;
};
5 changes: 2 additions & 3 deletions iocore/net/quic/QUICPacketFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,9 @@ QUICPacketFactory::create_initial_packet(uint8_t *packet_buf, QUICConnectionId d
}

QUICPacketUPtr
QUICPacketFactory::create_retry_packet(QUICConnectionId destination_cid, QUICConnectionId source_cid,
QUICConnectionId original_dcid, QUICRetryToken &token)
QUICPacketFactory::create_retry_packet(QUICConnectionId destination_cid, QUICConnectionId source_cid, QUICRetryToken &token)
{
return QUICPacketUPtr(new QUICRetryPacket(QUIC_SUPPORTED_VERSIONS[0], destination_cid, source_cid, original_dcid, token),
return QUICPacketUPtr(new QUICRetryPacket(QUIC_SUPPORTED_VERSIONS[0], destination_cid, source_cid, token),
&QUICPacketDeleter::delete_packet_new);
}

Expand Down
3 changes: 1 addition & 2 deletions iocore/net/quic/QUICPacketFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ class QUICPacketFactory
static QUICPacketUPtr create_null_packet();
static QUICPacketUPtr create_version_negotiation_packet(QUICConnectionId dcid, QUICConnectionId scid);
static QUICPacketUPtr create_stateless_reset_packet(QUICStatelessResetToken stateless_reset_token);
static QUICPacketUPtr create_retry_packet(QUICConnectionId destination_cid, QUICConnectionId source_cid,
QUICConnectionId original_dcid, QUICRetryToken &token);
static QUICPacketUPtr create_retry_packet(QUICConnectionId destination_cid, QUICConnectionId source_cid, QUICRetryToken &token);

QUICPacketFactory(const QUICPacketProtectionKeyInfo &pp_key_info) : _pp_key_info(pp_key_info), _pp_protector(pp_key_info) {}

Expand Down
45 changes: 23 additions & 22 deletions iocore/net/quic/test/test_QUICPacket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,25 +92,27 @@ TEST_CASE("Receiving Packet", "[quic]")
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID
0x08, // SCID Len
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID
0x08, // ODCID Len
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // Original Destination Connection ID
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // Retry Token
0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Retry Token
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, //
0x10, 0x11, 0x12, 0x13, 0x14, 0xf0, 0xf1, 0xf2, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Retry Integrity Tag
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
Ptr<IOBufferBlock> input_ibb = make_ptr<IOBufferBlock>(new_IOBufferBlock());
input_ibb->set_internal(input, sizeof(input), BUFFER_SIZE_NOT_ALLOCATED);

const uint8_t retry_token[] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0};
const uint8_t retry_token[] = {
0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0xf0, 0xf1, 0xf2,
};

QUICRetryPacketR packet(nullptr, {}, {}, input_ibb);
CHECK(packet.type() == QUICPacketType::RETRY);
CHECK(packet.size() == sizeof(input));
CHECK(packet.destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04\x05\x06\x07\x08"), 8));
CHECK(packet.source_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8));

CHECK(packet.original_dcid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x08\x07\x06\x05\x04\x03\x02\x01"), 8));

CHECK(memcmp(packet.token().buf(), retry_token, 16) == 0);
CHECK(memcmp(packet.token().buf(), retry_token, 24) == 0);
CHECK(packet.version() == 0x11223344);
}

Expand Down Expand Up @@ -263,27 +265,25 @@ TEST_CASE("Sending Packet", "[quic]")
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID
0x08, // SCID Len
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID
0x08, // ODCID Len
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // Original Destination Connection ID
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // Retry Token
0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Retry Token
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, //
0x10, 0x11, 0x12, 0x13, 0x14, 0xf0, 0xf1, 0xf2, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Retry Integrity Tag
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
QUICRetryToken token(expected + 30, 16);
QUICRetryToken token(expected + 23, 24);

QUICRetryPacket packet(0x11223344, {reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04\x05\x06\x07\x08"), 8},
{reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8},
{reinterpret_cast<const uint8_t *>("\x08\x07\x06\x05\x04\x03\x02\x01"), 8}, token);
{reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8}, token);
CHECK(packet.size() == sizeof(expected));
CHECK(packet.type() == QUICPacketType::RETRY);
CHECK((packet.destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04\x05\x06\x07\x08"), 8)));
CHECK((packet.source_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8)));
CHECK(packet.version() == 0x11223344);
CHECK((packet.original_dcid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x08\x07\x06\x05\x04\x03\x02\x01"), 8)));

packet.store(buf, &len);
CHECK(len == packet.size());
CHECK(memcmp(buf, expected, 22) == 0);
CHECK(memcmp(buf + 22, expected + 22, 8) == 0);
CHECK(memcmp(buf, expected, sizeof(expected) - 16) == 0);
}
}

Expand Down Expand Up @@ -362,10 +362,11 @@ TEST_CASE("read_essential_info", "[quic]")
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Destination Connection ID
0x08, // SCID Len
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // Source Connection ID
0x08, // ODCID Len
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // Original Destination Connection ID
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, // Retry Token
0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Retry Token
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, //
0x10, 0x11, 0x12, 0x13, 0x14, 0xf0, 0xf1, 0xf2, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Retry Integrity Tag
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

QUICConnectionId expected_dcid(input + 6, 8);
Expand Down
4 changes: 1 addition & 3 deletions iocore/net/quic/test/test_QUICPacketFactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,14 @@ TEST_CASE("QUICPacketFactory_Create_Retry", "[quic]")

QUICPacketUPtr packet =
factory.create_retry_packet(QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04"), 4),
QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14"), 4),
QUICConnectionId(reinterpret_cast<const uint8_t *>("\x04\x03\x02\x01"), 4), token);
QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14"), 4), token);

REQUIRE(packet != nullptr);

QUICRetryPacket &retry_packet = static_cast<QUICRetryPacket &>(*packet);
CHECK(retry_packet.type() == QUICPacketType::RETRY);
CHECK(retry_packet.destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04"), 4));
CHECK(retry_packet.version() == QUIC_SUPPORTED_VERSIONS[0]);
CHECK(retry_packet.original_dcid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x04\x03\x02\x01"), 4));
CHECK(retry_packet.token() == token);
}

Expand Down

0 comments on commit bc33fc3

Please sign in to comment.