blob: 573e1a89077f94e95a99d0d10002de4b07d9f79d [file] [log] [blame]
/** @file
*
* A brief file description
*
* @section license License
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "catch.hpp"
#include "quic/QUICPacket.h"
TEST_CASE("QUICPacketHeader - Long", "[quic]")
{
SECTION("Long Header (load) Version Negotiation Packet")
{
const uint8_t input[] = {
0xc0, // Long header, Type: NONE
0x00, 0x00, 0x00, 0x00, // Version
0x08, // DCID Len
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
0x00, 0x00, 0x00, 0x08, // Supported Version 1
0x00, 0x00, 0x00, 0x09, // Supported Version 1
};
ats_unique_buf uinput = ats_unique_malloc(sizeof(input));
memcpy(uinput.get(), input, sizeof(input));
QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, {}, std::move(uinput), sizeof(input), 0);
CHECK(header->size() == sizeof(input) - 8);
CHECK(header->packet_size() == sizeof(input));
CHECK(header->type() == QUICPacketType::VERSION_NEGOTIATION);
CHECK(
(header->destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04\x05\x06\x07\x08"), 8)));
CHECK((header->source_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8)));
CHECK(header->has_version() == true);
CHECK(header->version() == 0x00000000);
}
SECTION("Long Header (load) INITIAL Packet")
{
const uint8_t input[] = {
0xc3, // Long header, Type: INITIAL
0x11, 0x22, 0x33, 0x44, // Version
0x08, // DCID Len
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
0x00, // Token Length (i), Token (*)
0x06, // Length
0x01, 0x23, 0x45, 0x67, // Packet number
0xff, 0xff, // Payload (dummy)
};
ats_unique_buf uinput = ats_unique_malloc(sizeof(input));
memcpy(uinput.get(), input, sizeof(input));
QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, {}, std::move(uinput), sizeof(input), 0);
CHECK(header->size() == sizeof(input) - 2); // Packet Length - Payload Length
CHECK(header->packet_size() == sizeof(input));
CHECK(header->type() == QUICPacketType::INITIAL);
CHECK(
(header->destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04\x05\x06\x07\x08"), 8)));
CHECK((header->source_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8)));
CHECK(header->packet_number() == 0x01234567);
CHECK(header->has_version() == true);
CHECK(header->version() == 0x11223344);
}
SECTION("Long Header (load) RETRY Packet")
{
const uint8_t input[] = {
0xf5, // Long header, Type: RETRY
0x11, 0x22, 0x33, 0x44, // Version
0x08, // DCID Len
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,
};
ats_unique_buf uinput = ats_unique_malloc(sizeof(input));
memcpy(uinput.get(), input, sizeof(input));
const uint8_t retry_token[] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0};
QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, {}, std::move(uinput), sizeof(input), 0);
CHECK(header->size() == sizeof(input) - 16); // Packet Length - Payload Length (Retry Token)
CHECK(header->packet_size() == sizeof(input));
CHECK(header->type() == QUICPacketType::RETRY);
CHECK(
(header->destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04\x05\x06\x07\x08"), 8)));
CHECK((header->source_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8)));
QUICPacketLongHeader *retry_header = static_cast<QUICPacketLongHeader *>(header.get());
CHECK((retry_header->original_dcid() ==
QUICConnectionId(reinterpret_cast<const uint8_t *>("\x08\x07\x06\x05\x04\x03\x02\x01"), 8)));
CHECK(memcmp(header->payload(), retry_token, 16) == 0);
CHECK(header->has_version() == true);
CHECK(header->version() == 0x11223344);
}
SECTION("Long Header (parse) INITIAL Packet")
{
const uint8_t buf[] = {
0xc3, // Long header, Type: INITIAL
0x11, 0x22, 0x33, 0x44, // Version
0x08, // DCID Len
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
0x00, // Token Length (i), Token (*)
0x06, // Length
0x01, 0x23, 0x45, 0x67, // Packet number
0xff, 0xff, // Payload (dummy)
};
QUICPacketType type;
REQUIRE(QUICPacketLongHeader::type(type, buf, sizeof(buf)));
CHECK(type == QUICPacketType::INITIAL);
QUICVersion version;
REQUIRE(QUICPacketLongHeader::version(version, buf, sizeof(buf)));
CHECK(version == 0x11223344);
uint8_t dcil;
REQUIRE(QUICPacketLongHeader::dcil(dcil, buf, sizeof(buf)));
CHECK(dcil == 8);
uint8_t scil;
REQUIRE(QUICPacketLongHeader::scil(scil, buf, sizeof(buf)));
CHECK(dcil == 8);
size_t token_length;
uint8_t token_length_field_len;
size_t token_length_field_offset;
REQUIRE(QUICPacketLongHeader::token_length(token_length, token_length_field_len, token_length_field_offset, buf, sizeof(buf)));
CHECK(token_length == 0);
CHECK(token_length_field_len == 1);
CHECK(token_length_field_offset == 23);
size_t length;
uint8_t length_field_len;
size_t length_field_offset;
REQUIRE(QUICPacketLongHeader::length(length, length_field_len, length_field_offset, buf, sizeof(buf)));
CHECK(length == 6);
CHECK(length_field_len == 1);
CHECK(length_field_offset == 24);
size_t pn_offset;
REQUIRE(QUICPacketLongHeader::packet_number_offset(pn_offset, buf, sizeof(buf)));
CHECK(pn_offset == 25);
size_t packet_length;
REQUIRE(QUICPacketLongHeader::packet_length(packet_length, buf, sizeof(buf)));
CHECK(packet_length == sizeof(buf));
}
SECTION("Long Header (store) INITIAL Packet")
{
uint8_t buf[64] = {0};
size_t len = 0;
const uint8_t expected[] = {
0xc3, // Long header, Type: INITIAL
0x11, 0x22, 0x33, 0x44, // Version
0x08, // DCID Len
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
0x00, // Token Length (i), Token (*)
0x19, // Length (Not 0x09 because it will have 16 bytes of AEAD tag)
0x01, 0x23, 0x45, 0x67, // Packet number
0x11, 0x22, 0x33, 0x44, 0x55, // Payload (dummy)
};
ats_unique_buf payload = ats_unique_malloc(5);
memcpy(payload.get(), expected + 17, 5);
QUICPacketHeaderUPtr header = QUICPacketHeader::build(
QUICPacketType::INITIAL, QUICKeyPhase::INITIAL, {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}, 0x01234567, 0, 0x11223344, true,
std::move(payload), 5);
CHECK(header->size() == sizeof(expected) - 5);
CHECK(header->packet_size() == sizeof(expected));
CHECK(header->type() == QUICPacketType::INITIAL);
CHECK(
(header->destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04\x05\x06\x07\x08"), 8)));
CHECK((header->source_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8)));
CHECK(header->packet_number() == 0x01234567);
CHECK(header->has_version() == true);
CHECK(header->version() == 0x11223344);
CHECK(header->is_crypto_packet());
header->store(buf, &len);
CHECK(len == header->size());
CHECK(memcmp(buf, expected, len) == 0);
}
SECTION("Long Header (store) RETRY Packet")
{
uint8_t buf[64] = {0};
size_t len = 0;
const uint8_t expected[] = {
0xf0, // Long header, Type: RETRY
0x11, 0x22, 0x33, 0x44, // Version
0x08, // DCID Len
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,
};
ats_unique_buf payload = ats_unique_malloc(16);
memcpy(payload.get(), expected + 30, 16);
QUICPacketHeaderUPtr header =
QUICPacketHeader::build(QUICPacketType::RETRY, QUICKeyPhase::INITIAL, 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}, std::move(payload), 16);
CHECK(header->size() == sizeof(expected) - 16);
CHECK(header->packet_size() == sizeof(expected));
CHECK(header->type() == QUICPacketType::RETRY);
CHECK(
(header->destination_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x01\x02\x03\x04\x05\x06\x07\x08"), 8)));
CHECK((header->source_cid() == QUICConnectionId(reinterpret_cast<const uint8_t *>("\x11\x12\x13\x14\x15\x16\x17\x18"), 8)));
CHECK(header->has_version() == true);
CHECK(header->version() == 0x11223344);
QUICPacketLongHeader *retry_header = static_cast<QUICPacketLongHeader *>(header.get());
CHECK((retry_header->original_dcid() ==
QUICConnectionId(reinterpret_cast<const uint8_t *>("\x08\x07\x06\x05\x04\x03\x02\x01"), 8)));
header->store(buf, &len);
CHECK(len == header->size());
CHECK(memcmp(buf, expected, 22) == 0);
CHECK(memcmp(buf + 22, expected + 22, 8) == 0);
}
}
TEST_CASE("QUICPacketHeader - Short", "[quic]")
{
const uint8_t raw_dcid[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Destination Connection ID (144)
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, //
0x10, 0x11, //
};
QUICConnectionId dcid(raw_dcid, sizeof(raw_dcid));
SECTION("Short Header (load)")
{
const uint8_t input[] = {
0x43, // Short header with (K=0)
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Destination Connection ID (144)
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, //
0x10, 0x11, //
0x01, 0x23, 0x45, 0x67, // Packet number
0xff, 0xff, // Payload (dummy)
};
ats_unique_buf uinput = ats_unique_malloc(sizeof(input));
memcpy(uinput.get(), input, sizeof(input));
QUICPacketHeaderUPtr header = QUICPacketHeader::load({}, {}, std::move(uinput), sizeof(input), 0);
CHECK(header->size() == 23);
CHECK(header->packet_size() == 25);
CHECK(header->key_phase() == QUICKeyPhase::PHASE_0);
CHECK(header->destination_cid() == dcid);
CHECK(header->packet_number() == 0x01234567);
CHECK(header->has_version() == false);
}
SECTION("Short Header (store)")
{
uint8_t buf[32] = {0};
size_t len = 0;
const uint8_t expected[] = {
0x43, // Short header with (K=0)
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // Destination Connection ID (144)
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, //
0x10, 0x11, //
0x01, 0x23, 0x45, 0x67, // Packet number
0x11, 0x22, 0x33, 0x44, 0x55, // Protected Payload
};
size_t payload_len = 5;
size_t header_len = sizeof(expected) - 5;
ats_unique_buf payload = ats_unique_malloc(payload_len);
memcpy(payload.get(), expected + header_len, payload_len);
QUICPacketHeaderUPtr header =
QUICPacketHeader::build(QUICPacketType::PROTECTED, QUICKeyPhase::PHASE_0, dcid, 0x01234567, 0, std::move(payload), 32);
CHECK(header->size() == 23);
CHECK(header->packet_size() == 0);
CHECK(header->key_phase() == QUICKeyPhase::PHASE_0);
CHECK(header->type() == QUICPacketType::PROTECTED);
CHECK(header->destination_cid() == dcid);
CHECK(header->packet_number() == 0x01234567);
CHECK(header->has_version() == false);
header->store(buf, &len);
CHECK(len == header_len);
CHECK(memcmp(buf, expected, header_len) == 0);
}
}
TEST_CASE("Encoded Packet Number Length", "[quic]")
{
QUICPacketNumber base = 0xabe8bc;
CHECK(QUICPacket::calc_packet_number_len(0xace8fe, base) == 3);
}
TEST_CASE("Encoding Packet Number", "[quic]")
{
QUICPacketNumber dst = 0;
QUICPacketNumber src = 0xaa831f94;
QUICPacket::encode_packet_number(dst, src, 2);
CHECK(dst == 0x1f94);
}
TEST_CASE("Decoding Packet Number 1", "[quic]")
{
QUICPacketNumber dst = 0;
QUICPacketNumber src = 0x9b3;
size_t len = 2;
QUICPacketNumber base = 0xaa82f30e;
QUICPacket::decode_packet_number(dst, src, len, base);
CHECK(dst == 0xaa8309b3);
}