mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-01 01:44:22 +03:00
Remove throws from PacketNumberCipher
Summary: Continuing the theme. Reviewed By: kvtsoy Differential Revision: D74944002 fbshipit-source-id: 9f23780aada2841ee88a365b93850fde4bb27a70
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ab8a6386c2
commit
92c50dad6f
@ -309,13 +309,19 @@ continuousMemoryBuildScheduleEncrypt(
|
|||||||
packetBuf->prepend(headerLen);
|
packetBuf->prepend(headerLen);
|
||||||
|
|
||||||
HeaderForm headerForm = packet->packet.header.getHeaderForm();
|
HeaderForm headerForm = packet->packet.header.getHeaderForm();
|
||||||
encryptPacketHeader(
|
auto headerEncryptResult = encryptPacketHeader(
|
||||||
headerForm,
|
headerForm,
|
||||||
packetBuf->writableData(),
|
packetBuf->writableData(),
|
||||||
headerLen,
|
headerLen,
|
||||||
packetBuf->data() + headerLen,
|
packetBuf->data() + headerLen,
|
||||||
packetBuf->length() - headerLen,
|
packetBuf->length() - headerLen,
|
||||||
headerCipher);
|
headerCipher);
|
||||||
|
if (headerEncryptResult.hasError()) {
|
||||||
|
return folly::makeUnexpected(headerEncryptResult.error());
|
||||||
|
}
|
||||||
|
if (headerEncryptResult.hasError()) {
|
||||||
|
return folly::makeUnexpected(headerEncryptResult.error());
|
||||||
|
}
|
||||||
CHECK(!packetBuf->isChained());
|
CHECK(!packetBuf->isChained());
|
||||||
auto encodedSize = packetBuf->length();
|
auto encodedSize = packetBuf->length();
|
||||||
auto encodedBodySize = encodedSize - headerLen;
|
auto encodedBodySize = encodedSize - headerLen;
|
||||||
@ -413,13 +419,16 @@ iobufChainBasedBuildScheduleEncrypt(
|
|||||||
packetBuf->append(headerLen + bodyLen + aead.getCipherOverhead());
|
packetBuf->append(headerLen + bodyLen + aead.getCipherOverhead());
|
||||||
|
|
||||||
HeaderForm headerForm = packet->packet.header.getHeaderForm();
|
HeaderForm headerForm = packet->packet.header.getHeaderForm();
|
||||||
encryptPacketHeader(
|
auto headerEncryptResult = encryptPacketHeader(
|
||||||
headerForm,
|
headerForm,
|
||||||
packetBuf->writableData(),
|
packetBuf->writableData(),
|
||||||
headerLen,
|
headerLen,
|
||||||
packetBuf->data() + headerLen,
|
packetBuf->data() + headerLen,
|
||||||
packetBuf->length() - headerLen,
|
packetBuf->length() - headerLen,
|
||||||
headerCipher);
|
headerCipher);
|
||||||
|
if (headerEncryptResult.hasError()) {
|
||||||
|
return folly::makeUnexpected(headerEncryptResult.error());
|
||||||
|
}
|
||||||
auto encodedSize = packetBuf->computeChainDataLength();
|
auto encodedSize = packetBuf->computeChainDataLength();
|
||||||
auto encodedBodySize = encodedSize - headerLen;
|
auto encodedBodySize = encodedSize - headerLen;
|
||||||
if (encodedSize > connection.udpSendPacketLen) {
|
if (encodedSize > connection.udpSendPacketLen) {
|
||||||
@ -1525,7 +1534,7 @@ void writeShortClose(
|
|||||||
headerCipher);
|
headerCipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
void encryptPacketHeader(
|
folly::Expected<folly::Unit, QuicError> encryptPacketHeader(
|
||||||
HeaderForm headerForm,
|
HeaderForm headerForm,
|
||||||
uint8_t* header,
|
uint8_t* header,
|
||||||
size_t headerLen,
|
size_t headerLen,
|
||||||
@ -1546,12 +1555,19 @@ void encryptPacketHeader(
|
|||||||
MutableByteRange packetNumByteRange(
|
MutableByteRange packetNumByteRange(
|
||||||
header + headerLen - packetNumberLength, packetNumberLength);
|
header + headerLen - packetNumberLength, packetNumberLength);
|
||||||
if (headerForm == HeaderForm::Short) {
|
if (headerForm == HeaderForm::Short) {
|
||||||
headerCipher.encryptShortHeader(
|
auto result = headerCipher.encryptShortHeader(
|
||||||
sample, initialByteRange, packetNumByteRange);
|
sample, initialByteRange, packetNumByteRange);
|
||||||
|
if (result.hasError()) {
|
||||||
|
return folly::makeUnexpected(result.error());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
headerCipher.encryptLongHeader(
|
auto result = headerCipher.encryptLongHeader(
|
||||||
sample, initialByteRange, packetNumByteRange);
|
sample, initialByteRange, packetNumByteRange);
|
||||||
|
if (result.hasError()) {
|
||||||
|
return folly::makeUnexpected(result.error());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return folly::unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -268,7 +268,7 @@ void writeShortClose(
|
|||||||
* whether or not there are enough bytes to sample for the header encryption
|
* whether or not there are enough bytes to sample for the header encryption
|
||||||
* from the encryptedBody via a CHECK.
|
* from the encryptedBody via a CHECK.
|
||||||
*/
|
*/
|
||||||
void encryptPacketHeader(
|
folly::Expected<folly::Unit, QuicError> encryptPacketHeader(
|
||||||
HeaderForm headerForm,
|
HeaderForm headerForm,
|
||||||
uint8_t* header,
|
uint8_t* header,
|
||||||
size_t headerLen,
|
size_t headerLen,
|
||||||
|
@ -76,7 +76,10 @@ mvfst_cpp_library(
|
|||||||
":types",
|
":types",
|
||||||
],
|
],
|
||||||
exported_deps = [
|
exported_deps = [
|
||||||
|
"//folly:expected",
|
||||||
|
"//folly:unit",
|
||||||
"//folly/io:iobuf",
|
"//folly/io:iobuf",
|
||||||
|
"//quic:exception",
|
||||||
"//quic/common:buf_util",
|
"//quic/common:buf_util",
|
||||||
"//quic/common:optional",
|
"//quic/common:optional",
|
||||||
],
|
],
|
||||||
|
@ -13,14 +13,18 @@
|
|||||||
|
|
||||||
namespace quic {
|
namespace quic {
|
||||||
|
|
||||||
void PacketNumberCipher::decipherHeader(
|
folly::Expected<folly::Unit, QuicError> PacketNumberCipher::decipherHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes,
|
MutableByteRange packetNumberBytes,
|
||||||
uint8_t initialByteMask,
|
uint8_t initialByteMask,
|
||||||
uint8_t /* packetNumLengthMask */) const {
|
uint8_t /* packetNumLengthMask */) const {
|
||||||
CHECK_EQ(packetNumberBytes.size(), kMaxPacketNumEncodingSize);
|
CHECK_EQ(packetNumberBytes.size(), kMaxPacketNumEncodingSize);
|
||||||
HeaderProtectionMask headerMask = mask(sample);
|
auto maskResult = mask(sample);
|
||||||
|
if (maskResult.hasError()) {
|
||||||
|
return folly::makeUnexpected(maskResult.error());
|
||||||
|
}
|
||||||
|
HeaderProtectionMask headerMask = std::move(maskResult.value());
|
||||||
// Mask size should be > packet number length + 1.
|
// Mask size should be > packet number length + 1.
|
||||||
DCHECK_GE(headerMask.size(), 5);
|
DCHECK_GE(headerMask.size(), 5);
|
||||||
initialByte.data()[0] ^= headerMask.data()[0] & initialByteMask;
|
initialByte.data()[0] ^= headerMask.data()[0] & initialByteMask;
|
||||||
@ -28,15 +32,20 @@ void PacketNumberCipher::decipherHeader(
|
|||||||
for (size_t i = 0; i < packetNumLength; ++i) {
|
for (size_t i = 0; i < packetNumLength; ++i) {
|
||||||
packetNumberBytes.data()[i] ^= headerMask.data()[i + 1];
|
packetNumberBytes.data()[i] ^= headerMask.data()[i + 1];
|
||||||
}
|
}
|
||||||
|
return folly::unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketNumberCipher::cipherHeader(
|
folly::Expected<folly::Unit, QuicError> PacketNumberCipher::cipherHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes,
|
MutableByteRange packetNumberBytes,
|
||||||
uint8_t initialByteMask,
|
uint8_t initialByteMask,
|
||||||
uint8_t /* packetNumLengthMask */) const {
|
uint8_t /* packetNumLengthMask */) const {
|
||||||
HeaderProtectionMask headerMask = mask(sample);
|
auto maskResult = mask(sample);
|
||||||
|
if (maskResult.hasError()) {
|
||||||
|
return folly::makeUnexpected(maskResult.error());
|
||||||
|
}
|
||||||
|
HeaderProtectionMask headerMask = std::move(maskResult.value());
|
||||||
// Mask size should be > packet number length + 1.
|
// Mask size should be > packet number length + 1.
|
||||||
DCHECK_GE(headerMask.size(), kMaxPacketNumEncodingSize + 1);
|
DCHECK_GE(headerMask.size(), kMaxPacketNumEncodingSize + 1);
|
||||||
size_t packetNumLength = parsePacketNumberLength(*initialByte.data());
|
size_t packetNumLength = parsePacketNumberLength(*initialByte.data());
|
||||||
@ -44,13 +53,14 @@ void PacketNumberCipher::cipherHeader(
|
|||||||
for (size_t i = 0; i < packetNumLength; ++i) {
|
for (size_t i = 0; i < packetNumLength; ++i) {
|
||||||
packetNumberBytes.data()[i] ^= headerMask.data()[i + 1];
|
packetNumberBytes.data()[i] ^= headerMask.data()[i + 1];
|
||||||
}
|
}
|
||||||
|
return folly::unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketNumberCipher::decryptLongHeader(
|
folly::Expected<folly::Unit, QuicError> PacketNumberCipher::decryptLongHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes) const {
|
MutableByteRange packetNumberBytes) const {
|
||||||
decipherHeader(
|
return decipherHeader(
|
||||||
sample,
|
sample,
|
||||||
initialByte,
|
initialByte,
|
||||||
packetNumberBytes,
|
packetNumberBytes,
|
||||||
@ -58,11 +68,11 @@ void PacketNumberCipher::decryptLongHeader(
|
|||||||
LongHeader::kPacketNumLenMask);
|
LongHeader::kPacketNumLenMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketNumberCipher::decryptShortHeader(
|
folly::Expected<folly::Unit, QuicError> PacketNumberCipher::decryptShortHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes) const {
|
MutableByteRange packetNumberBytes) const {
|
||||||
decipherHeader(
|
return decipherHeader(
|
||||||
sample,
|
sample,
|
||||||
initialByte,
|
initialByte,
|
||||||
packetNumberBytes,
|
packetNumberBytes,
|
||||||
@ -70,11 +80,11 @@ void PacketNumberCipher::decryptShortHeader(
|
|||||||
ShortHeader::kPacketNumLenMask);
|
ShortHeader::kPacketNumLenMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketNumberCipher::encryptLongHeader(
|
folly::Expected<folly::Unit, QuicError> PacketNumberCipher::encryptLongHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes) const {
|
MutableByteRange packetNumberBytes) const {
|
||||||
cipherHeader(
|
return cipherHeader(
|
||||||
sample,
|
sample,
|
||||||
initialByte,
|
initialByte,
|
||||||
packetNumberBytes,
|
packetNumberBytes,
|
||||||
@ -82,11 +92,11 @@ void PacketNumberCipher::encryptLongHeader(
|
|||||||
LongHeader::kPacketNumLenMask);
|
LongHeader::kPacketNumLenMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PacketNumberCipher::encryptShortHeader(
|
folly::Expected<folly::Unit, QuicError> PacketNumberCipher::encryptShortHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes) const {
|
MutableByteRange packetNumberBytes) const {
|
||||||
cipherHeader(
|
return cipherHeader(
|
||||||
sample,
|
sample,
|
||||||
initialByte,
|
initialByte,
|
||||||
packetNumberBytes,
|
packetNumberBytes,
|
||||||
|
@ -7,7 +7,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <folly/Expected.h>
|
||||||
|
#include <folly/Unit.h>
|
||||||
#include <folly/io/Cursor.h>
|
#include <folly/io/Cursor.h>
|
||||||
|
#include <quic/QuicException.h>
|
||||||
#include <quic/common/BufUtil.h>
|
#include <quic/common/BufUtil.h>
|
||||||
#include <quic/common/Optional.h>
|
#include <quic/common/Optional.h>
|
||||||
|
|
||||||
@ -20,9 +23,11 @@ class PacketNumberCipher {
|
|||||||
public:
|
public:
|
||||||
virtual ~PacketNumberCipher() = default;
|
virtual ~PacketNumberCipher() = default;
|
||||||
|
|
||||||
virtual void setKey(ByteRange key) = 0;
|
[[nodiscard]] virtual folly::Expected<folly::Unit, QuicError> setKey(
|
||||||
|
ByteRange key) = 0;
|
||||||
|
|
||||||
virtual HeaderProtectionMask mask(ByteRange sample) const = 0;
|
[[nodiscard]] virtual folly::Expected<HeaderProtectionMask, QuicError> mask(
|
||||||
|
ByteRange sample) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decrypts a long header from a sample.
|
* Decrypts a long header from a sample.
|
||||||
@ -30,7 +35,8 @@ class PacketNumberCipher {
|
|||||||
* initialByte is the initial byte.
|
* initialByte is the initial byte.
|
||||||
* packetNumberBytes should be supplied with at least 4 bytes.
|
* packetNumberBytes should be supplied with at least 4 bytes.
|
||||||
*/
|
*/
|
||||||
virtual void decryptLongHeader(
|
[[nodiscard]] virtual folly::Expected<folly::Unit, QuicError>
|
||||||
|
decryptLongHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes) const;
|
MutableByteRange packetNumberBytes) const;
|
||||||
@ -41,7 +47,8 @@ class PacketNumberCipher {
|
|||||||
* initialByte is the initial byte.
|
* initialByte is the initial byte.
|
||||||
* packetNumberBytes should be supplied with at least 4 bytes.
|
* packetNumberBytes should be supplied with at least 4 bytes.
|
||||||
*/
|
*/
|
||||||
virtual void decryptShortHeader(
|
[[nodiscard]] virtual folly::Expected<folly::Unit, QuicError>
|
||||||
|
decryptShortHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes) const;
|
MutableByteRange packetNumberBytes) const;
|
||||||
@ -51,7 +58,8 @@ class PacketNumberCipher {
|
|||||||
* sample should be 16 bytes long.
|
* sample should be 16 bytes long.
|
||||||
* initialByte is the initial byte.
|
* initialByte is the initial byte.
|
||||||
*/
|
*/
|
||||||
virtual void encryptLongHeader(
|
[[nodiscard]] virtual folly::Expected<folly::Unit, QuicError>
|
||||||
|
encryptLongHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes) const;
|
MutableByteRange packetNumberBytes) const;
|
||||||
@ -61,7 +69,8 @@ class PacketNumberCipher {
|
|||||||
* sample should be 16 bytes long.
|
* sample should be 16 bytes long.
|
||||||
* initialByte is the initial byte.
|
* initialByte is the initial byte.
|
||||||
*/
|
*/
|
||||||
virtual void encryptShortHeader(
|
[[nodiscard]] virtual folly::Expected<folly::Unit, QuicError>
|
||||||
|
encryptShortHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes) const;
|
MutableByteRange packetNumberBytes) const;
|
||||||
@ -69,22 +78,22 @@ class PacketNumberCipher {
|
|||||||
/**
|
/**
|
||||||
* Returns the length of key needed for the pn cipher.
|
* Returns the length of key needed for the pn cipher.
|
||||||
*/
|
*/
|
||||||
virtual size_t keyLength() const = 0;
|
[[nodiscard]] virtual size_t keyLength() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the packet protection key
|
* Get the packet protection key
|
||||||
*/
|
*/
|
||||||
virtual const BufPtr& getKey() const = 0;
|
[[nodiscard]] virtual const BufPtr& getKey() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void cipherHeader(
|
[[nodiscard]] virtual folly::Expected<folly::Unit, QuicError> cipherHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes,
|
MutableByteRange packetNumberBytes,
|
||||||
uint8_t initialByteMask,
|
uint8_t initialByteMask,
|
||||||
uint8_t packetNumLengthMask) const;
|
uint8_t packetNumLengthMask) const;
|
||||||
|
|
||||||
virtual void decipherHeader(
|
[[nodiscard]] virtual folly::Expected<folly::Unit, QuicError> decipherHeader(
|
||||||
ByteRange sample,
|
ByteRange sample,
|
||||||
MutableByteRange initialByte,
|
MutableByteRange initialByte,
|
||||||
MutableByteRange packetNumberBytes,
|
MutableByteRange packetNumberBytes,
|
||||||
|
@ -91,7 +91,7 @@ static PacketDropReason getDecryptErrorReason(ProtectionType protectionType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CodecResult QuicReadCodec::parseLongHeaderPacket(
|
folly::Expected<CodecResult, QuicError> QuicReadCodec::parseLongHeaderPacket(
|
||||||
BufQueue& queue,
|
BufQueue& queue,
|
||||||
const AckStates& ackStates) {
|
const AckStates& ackStates) {
|
||||||
Cursor cursor(queue.front());
|
Cursor cursor(queue.front());
|
||||||
@ -213,8 +213,12 @@ CodecResult QuicReadCodec::parseLongHeaderPacket(
|
|||||||
MutableByteRange packetNumberByteRange(
|
MutableByteRange packetNumberByteRange(
|
||||||
currentPacketData->writableData() + packetNumberOffset,
|
currentPacketData->writableData() + packetNumberOffset,
|
||||||
kMaxPacketNumEncodingSize);
|
kMaxPacketNumEncodingSize);
|
||||||
headerCipher->decryptLongHeader(
|
auto decryptResult = headerCipher->decryptLongHeader(
|
||||||
folly::range(sample), initialByteRange, packetNumberByteRange);
|
folly::range(sample), initialByteRange, packetNumberByteRange);
|
||||||
|
if (decryptResult.hasError()) {
|
||||||
|
VLOG(4) << "Failed to decrypt long header " << connIdToHex();
|
||||||
|
return folly::makeUnexpected(decryptResult.error());
|
||||||
|
}
|
||||||
std::pair<PacketNum, size_t> packetNum = parsePacketNumber(
|
std::pair<PacketNum, size_t> packetNum = parsePacketNumber(
|
||||||
initialByteRange.data()[0], packetNumberByteRange, expectedNextPacketNum);
|
initialByteRange.data()[0], packetNumberByteRange, expectedNextPacketNum);
|
||||||
|
|
||||||
@ -260,7 +264,8 @@ CodecResult QuicReadCodec::parseLongHeaderPacket(
|
|||||||
return CodecResult(std::move(*packetRes));
|
return CodecResult(std::move(*packetRes));
|
||||||
}
|
}
|
||||||
|
|
||||||
CodecResult QuicReadCodec::tryParseShortHeaderPacket(
|
folly::Expected<CodecResult, QuicError>
|
||||||
|
QuicReadCodec::tryParseShortHeaderPacket(
|
||||||
BufPtr data,
|
BufPtr data,
|
||||||
const AckStates& ackStates,
|
const AckStates& ackStates,
|
||||||
size_t dstConnIdSize,
|
size_t dstConnIdSize,
|
||||||
@ -284,8 +289,12 @@ CodecResult QuicReadCodec::tryParseShortHeaderPacket(
|
|||||||
data->writableData() + packetNumberOffset, kMaxPacketNumEncodingSize);
|
data->writableData() + packetNumberOffset, kMaxPacketNumEncodingSize);
|
||||||
ByteRange sampleByteRange(data->writableData() + sampleOffset, sample.size());
|
ByteRange sampleByteRange(data->writableData() + sampleOffset, sample.size());
|
||||||
|
|
||||||
oneRttHeaderCipher_->decryptShortHeader(
|
auto decryptResult = oneRttHeaderCipher_->decryptShortHeader(
|
||||||
sampleByteRange, initialByteRange, packetNumberByteRange);
|
sampleByteRange, initialByteRange, packetNumberByteRange);
|
||||||
|
if (decryptResult.hasError()) {
|
||||||
|
VLOG(4) << "Failed to decrypt short header " << connIdToHex();
|
||||||
|
return folly::makeUnexpected(decryptResult.error());
|
||||||
|
}
|
||||||
std::pair<PacketNum, size_t> packetNum = parsePacketNumber(
|
std::pair<PacketNum, size_t> packetNum = parsePacketNumber(
|
||||||
initialByteRange.data()[0], packetNumberByteRange, expectedNextPacketNum);
|
initialByteRange.data()[0], packetNumberByteRange, expectedNextPacketNum);
|
||||||
auto shortHeader =
|
auto shortHeader =
|
||||||
@ -411,7 +420,11 @@ CodecResult QuicReadCodec::parsePacket(
|
|||||||
uint8_t initialByte = cursor.readBE<uint8_t>();
|
uint8_t initialByte = cursor.readBE<uint8_t>();
|
||||||
auto headerForm = getHeaderForm(initialByte);
|
auto headerForm = getHeaderForm(initialByte);
|
||||||
if (headerForm == HeaderForm::Long) {
|
if (headerForm == HeaderForm::Long) {
|
||||||
return parseLongHeaderPacket(queue, ackStates);
|
auto result = parseLongHeaderPacket(queue, ackStates);
|
||||||
|
if (result.hasError()) {
|
||||||
|
return CodecResult(CodecError(std::move(result.error())));
|
||||||
|
}
|
||||||
|
return std::move(result.value());
|
||||||
}
|
}
|
||||||
// Missing 1-rtt header cipher is the only case we wouldn't consider reset
|
// Missing 1-rtt header cipher is the only case we wouldn't consider reset
|
||||||
if (!currentOneRttReadCipher_ || !oneRttHeaderCipher_) {
|
if (!currentOneRttReadCipher_ || !oneRttHeaderCipher_) {
|
||||||
@ -447,8 +460,12 @@ CodecResult QuicReadCodec::parsePacket(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tryParseShortHeaderPacket(
|
auto result = tryParseShortHeaderPacket(
|
||||||
std::move(data), ackStates, dstConnIdSize, cursor);
|
std::move(data), ackStates, dstConnIdSize, cursor);
|
||||||
|
if (result.hasError()) {
|
||||||
|
return CodecResult(CodecError(std::move(result.error())));
|
||||||
|
}
|
||||||
|
return std::move(result.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QuicReadCodec::canInitiateKeyUpdate() const {
|
bool QuicReadCodec::canInitiateKeyUpdate() const {
|
||||||
|
@ -198,12 +198,12 @@ class QuicReadCodec {
|
|||||||
Optional<TimePoint> getHandshakeDoneTime();
|
Optional<TimePoint> getHandshakeDoneTime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CodecResult tryParseShortHeaderPacket(
|
folly::Expected<CodecResult, QuicError> tryParseShortHeaderPacket(
|
||||||
BufPtr data,
|
BufPtr data,
|
||||||
const AckStates& ackStates,
|
const AckStates& ackStates,
|
||||||
size_t dstConnIdSize,
|
size_t dstConnIdSize,
|
||||||
Cursor& cursor);
|
Cursor& cursor);
|
||||||
CodecResult parseLongHeaderPacket(
|
folly::Expected<CodecResult, QuicError> parseLongHeaderPacket(
|
||||||
BufQueue& queue,
|
BufQueue& queue,
|
||||||
const AckStates& ackStates);
|
const AckStates& ackStates);
|
||||||
|
|
||||||
|
@ -95,13 +95,19 @@ bool PacketGroupWriter::writeSingleQuicPacket(
|
|||||||
packetbuildBuf->prepend(headerLen);
|
packetbuildBuf->prepend(headerLen);
|
||||||
|
|
||||||
HeaderForm headerForm = packet.packet.header.getHeaderForm();
|
HeaderForm headerForm = packet.packet.header.getHeaderForm();
|
||||||
encryptPacketHeader(
|
auto headerEncryptResult = encryptPacketHeader(
|
||||||
headerForm,
|
headerForm,
|
||||||
packetbuildBuf->writableData(),
|
packetbuildBuf->writableData(),
|
||||||
headerLen,
|
headerLen,
|
||||||
packetbuildBuf->data() + headerLen,
|
packetbuildBuf->data() + headerLen,
|
||||||
packetbuildBuf->length() - headerLen,
|
packetbuildBuf->length() - headerLen,
|
||||||
headerCipher);
|
headerCipher);
|
||||||
|
if (headerEncryptResult.hasError()) {
|
||||||
|
throw QuicInternalException(
|
||||||
|
"DSR Send failed: Header encryption error: " +
|
||||||
|
headerEncryptResult.error().message,
|
||||||
|
LocalErrorCode::INTERNAL_ERROR);
|
||||||
|
}
|
||||||
CHECK(!packetbuildBuf->isChained());
|
CHECK(!packetbuildBuf->isChained());
|
||||||
auto encodedSize = packetbuildBuf->length();
|
auto encodedSize = packetbuildBuf->length();
|
||||||
// Include previous packets back.
|
// Include previous packets back.
|
||||||
|
@ -68,7 +68,9 @@ class CipherBuilder {
|
|||||||
throw std::runtime_error("Failed to create header cipher");
|
throw std::runtime_error("Failed to create header cipher");
|
||||||
}
|
}
|
||||||
auto headerCipher = std::move(headerCipherResult.value());
|
auto headerCipher = std::move(headerCipherResult.value());
|
||||||
headerCipher->setKey(packetProtectionKey->coalesce());
|
if (headerCipher->setKey(packetProtectionKey->coalesce()).hasError()) {
|
||||||
|
throw std::runtime_error("Failed to set header cipher key");
|
||||||
|
}
|
||||||
|
|
||||||
return {std::move(aead), std::move(headerCipher)};
|
return {std::move(aead), std::move(headerCipher)};
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,10 @@ FizzCryptoFactory::makePacketNumberCipher(ByteRange baseSecret) const {
|
|||||||
fizzFactory_->makeKeyDeriver(fizz::CipherSuite::TLS_AES_128_GCM_SHA256);
|
fizzFactory_->makeKeyDeriver(fizz::CipherSuite::TLS_AES_128_GCM_SHA256);
|
||||||
auto pnKey = deriver->expandLabel(
|
auto pnKey = deriver->expandLabel(
|
||||||
baseSecret, kQuicPNLabel, BufHelpers::create(0), pnCipher->keyLength());
|
baseSecret, kQuicPNLabel, BufHelpers::create(0), pnCipher->keyLength());
|
||||||
pnCipher->setKey(pnKey->coalesce());
|
auto setKeyResult = pnCipher->setKey(pnKey->coalesce());
|
||||||
|
if (setKeyResult.hasError()) {
|
||||||
|
return folly::makeUnexpected(setKeyResult.error());
|
||||||
|
}
|
||||||
return pnCipher;
|
return pnCipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,22 +9,26 @@
|
|||||||
|
|
||||||
namespace quic {
|
namespace quic {
|
||||||
|
|
||||||
static void setKeyImpl(
|
static folly::Expected<folly::Unit, QuicError> setKeyImpl(
|
||||||
folly::ssl::EvpCipherCtxUniquePtr& context,
|
folly::ssl::EvpCipherCtxUniquePtr& context,
|
||||||
const EVP_CIPHER* cipher,
|
const EVP_CIPHER* cipher,
|
||||||
ByteRange key) {
|
ByteRange key) {
|
||||||
DCHECK_EQ(key.size(), EVP_CIPHER_key_length(cipher));
|
DCHECK_EQ(key.size(), EVP_CIPHER_key_length(cipher));
|
||||||
context.reset(EVP_CIPHER_CTX_new());
|
context.reset(EVP_CIPHER_CTX_new());
|
||||||
if (context == nullptr) {
|
if (context == nullptr) {
|
||||||
throw std::runtime_error("Unable to allocate an EVP_CIPHER_CTX object");
|
return folly::makeUnexpected(QuicError(
|
||||||
|
TransportErrorCode::INTERNAL_ERROR,
|
||||||
|
"Unable to allocate an EVP_CIPHER_CTX object"));
|
||||||
}
|
}
|
||||||
if (EVP_EncryptInit_ex(context.get(), cipher, nullptr, key.data(), nullptr) !=
|
if (EVP_EncryptInit_ex(context.get(), cipher, nullptr, key.data(), nullptr) !=
|
||||||
1) {
|
1) {
|
||||||
throw std::runtime_error("Init error");
|
return folly::makeUnexpected(
|
||||||
|
QuicError(TransportErrorCode::INTERNAL_ERROR, "Init error"));
|
||||||
}
|
}
|
||||||
|
return folly::unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HeaderProtectionMask maskImpl(
|
static folly::Expected<HeaderProtectionMask, QuicError> maskImpl(
|
||||||
const folly::ssl::EvpCipherCtxUniquePtr& context,
|
const folly::ssl::EvpCipherCtxUniquePtr& context,
|
||||||
ByteRange sample) {
|
ByteRange sample) {
|
||||||
HeaderProtectionMask outMask;
|
HeaderProtectionMask outMask;
|
||||||
@ -35,19 +39,22 @@ static HeaderProtectionMask maskImpl(
|
|||||||
outMask.data(),
|
outMask.data(),
|
||||||
&outLen,
|
&outLen,
|
||||||
sample.data(),
|
sample.data(),
|
||||||
sample.size()) != 1 ||
|
static_cast<int>(sample.size())) != 1 ||
|
||||||
static_cast<HeaderProtectionMask::size_type>(outLen) != outMask.size()) {
|
static_cast<HeaderProtectionMask::size_type>(outLen) != outMask.size()) {
|
||||||
throw std::runtime_error("Encryption error");
|
return folly::makeUnexpected(
|
||||||
|
QuicError(TransportErrorCode::INTERNAL_ERROR, "Encryption error"));
|
||||||
}
|
}
|
||||||
return outMask;
|
return outMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Aes128PacketNumberCipher::setKey(ByteRange key) {
|
folly::Expected<folly::Unit, QuicError> Aes128PacketNumberCipher::setKey(
|
||||||
|
ByteRange key) {
|
||||||
pnKey_ = BufHelpers::copyBuffer(key);
|
pnKey_ = BufHelpers::copyBuffer(key);
|
||||||
return setKeyImpl(encryptCtx_, EVP_aes_128_ecb(), key);
|
return setKeyImpl(encryptCtx_, EVP_aes_128_ecb(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Aes256PacketNumberCipher::setKey(ByteRange key) {
|
folly::Expected<folly::Unit, QuicError> Aes256PacketNumberCipher::setKey(
|
||||||
|
ByteRange key) {
|
||||||
pnKey_ = BufHelpers::copyBuffer(key);
|
pnKey_ = BufHelpers::copyBuffer(key);
|
||||||
return setKeyImpl(encryptCtx_, EVP_aes_256_ecb(), key);
|
return setKeyImpl(encryptCtx_, EVP_aes_256_ecb(), key);
|
||||||
}
|
}
|
||||||
@ -60,11 +67,13 @@ const BufPtr& Aes256PacketNumberCipher::getKey() const {
|
|||||||
return pnKey_;
|
return pnKey_;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeaderProtectionMask Aes128PacketNumberCipher::mask(ByteRange sample) const {
|
folly::Expected<HeaderProtectionMask, QuicError> Aes128PacketNumberCipher::mask(
|
||||||
|
ByteRange sample) const {
|
||||||
return maskImpl(encryptCtx_, sample);
|
return maskImpl(encryptCtx_, sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeaderProtectionMask Aes256PacketNumberCipher::mask(ByteRange sample) const {
|
folly::Expected<HeaderProtectionMask, QuicError> Aes256PacketNumberCipher::mask(
|
||||||
|
ByteRange sample) const {
|
||||||
return maskImpl(encryptCtx_, sample);
|
return maskImpl(encryptCtx_, sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,13 +17,15 @@ class Aes128PacketNumberCipher : public PacketNumberCipher {
|
|||||||
public:
|
public:
|
||||||
~Aes128PacketNumberCipher() override = default;
|
~Aes128PacketNumberCipher() override = default;
|
||||||
|
|
||||||
void setKey(ByteRange key) override;
|
[[nodiscard]] folly::Expected<folly::Unit, QuicError> setKey(
|
||||||
|
ByteRange key) override;
|
||||||
|
|
||||||
const BufPtr& getKey() const override;
|
[[nodiscard]] const BufPtr& getKey() const override;
|
||||||
|
|
||||||
HeaderProtectionMask mask(ByteRange sample) const override;
|
[[nodiscard]] folly::Expected<HeaderProtectionMask, QuicError> mask(
|
||||||
|
ByteRange sample) const override;
|
||||||
|
|
||||||
size_t keyLength() const override;
|
[[nodiscard]] size_t keyLength() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
folly::ssl::EvpCipherCtxUniquePtr encryptCtx_;
|
folly::ssl::EvpCipherCtxUniquePtr encryptCtx_;
|
||||||
@ -35,13 +37,15 @@ class Aes256PacketNumberCipher : public PacketNumberCipher {
|
|||||||
public:
|
public:
|
||||||
~Aes256PacketNumberCipher() override = default;
|
~Aes256PacketNumberCipher() override = default;
|
||||||
|
|
||||||
void setKey(ByteRange key) override;
|
[[nodiscard]] folly::Expected<folly::Unit, QuicError> setKey(
|
||||||
|
ByteRange key) override;
|
||||||
|
|
||||||
const BufPtr& getKey() const override;
|
[[nodiscard]] const BufPtr& getKey() const override;
|
||||||
|
|
||||||
HeaderProtectionMask mask(ByteRange sample) const override;
|
[[nodiscard]] folly::Expected<HeaderProtectionMask, QuicError> mask(
|
||||||
|
ByteRange sample) const override;
|
||||||
|
|
||||||
size_t keyLength() const override;
|
[[nodiscard]] size_t keyLength() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
folly::ssl::EvpCipherCtxUniquePtr encryptCtx_;
|
folly::ssl::EvpCipherCtxUniquePtr encryptCtx_;
|
||||||
|
@ -51,6 +51,7 @@ class FizzCryptoFactoryTest : public Test {
|
|||||||
EXPECT_CALL(*mockPacketNumberCipher, setKey(_))
|
EXPECT_CALL(*mockPacketNumberCipher, setKey(_))
|
||||||
.WillOnce(Invoke([&](ByteRange key) {
|
.WillOnce(Invoke([&](ByteRange key) {
|
||||||
packetCipherKey_ = folly::IOBuf::copyBuffer(key);
|
packetCipherKey_ = folly::IOBuf::copyBuffer(key);
|
||||||
|
return folly::Expected<folly::Unit, QuicError>(folly::unit);
|
||||||
}));
|
}));
|
||||||
EXPECT_CALL(*mockPacketNumberCipher, keyLength())
|
EXPECT_CALL(*mockPacketNumberCipher, keyLength())
|
||||||
.WillRepeatedly(Return(fizz::AESGCM128::kKeyLength));
|
.WillRepeatedly(Return(fizz::AESGCM128::kKeyLength));
|
||||||
|
@ -66,23 +66,26 @@ TEST_P(LongPacketNumberCipherTest, TestEncryptDecrypt) {
|
|||||||
auto cipher = std::move(cipherResult.value());
|
auto cipher = std::move(cipherResult.value());
|
||||||
auto key = folly::unhexlify(GetParam().key);
|
auto key = folly::unhexlify(GetParam().key);
|
||||||
EXPECT_EQ(cipher->keyLength(), key.size());
|
EXPECT_EQ(cipher->keyLength(), key.size());
|
||||||
cipher->setKey(folly::range(key));
|
auto setKeyResult = cipher->setKey(folly::range(key));
|
||||||
|
ASSERT_FALSE(setKeyResult.hasError());
|
||||||
EXPECT_TRUE(!memcmp(cipher->getKey()->data(), key.c_str(), key.size()));
|
EXPECT_TRUE(!memcmp(cipher->getKey()->data(), key.c_str(), key.size()));
|
||||||
CipherBytes cipherBytes(
|
CipherBytes cipherBytes(
|
||||||
GetParam().sample,
|
GetParam().sample,
|
||||||
GetParam().decryptedInitialByte,
|
GetParam().decryptedInitialByte,
|
||||||
GetParam().decryptedPacketNumberBytes);
|
GetParam().decryptedPacketNumberBytes);
|
||||||
cipher->encryptLongHeader(
|
auto encryptResult = cipher->encryptLongHeader(
|
||||||
cipherBytes.sample,
|
cipherBytes.sample,
|
||||||
folly::range(cipherBytes.initial),
|
folly::range(cipherBytes.initial),
|
||||||
folly::range(cipherBytes.packetNumber));
|
folly::range(cipherBytes.packetNumber));
|
||||||
|
ASSERT_FALSE(encryptResult.hasError());
|
||||||
EXPECT_EQ(folly::hexlify(cipherBytes.initial), GetParam().initialByte);
|
EXPECT_EQ(folly::hexlify(cipherBytes.initial), GetParam().initialByte);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
folly::hexlify(cipherBytes.packetNumber), GetParam().packetNumberBytes);
|
folly::hexlify(cipherBytes.packetNumber), GetParam().packetNumberBytes);
|
||||||
cipher->decryptLongHeader(
|
auto decryptResult = cipher->decryptLongHeader(
|
||||||
cipherBytes.sample,
|
cipherBytes.sample,
|
||||||
folly::range(cipherBytes.initial),
|
folly::range(cipherBytes.initial),
|
||||||
folly::range(cipherBytes.packetNumber));
|
folly::range(cipherBytes.packetNumber));
|
||||||
|
ASSERT_FALSE(decryptResult.hasError());
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
folly::hexlify(cipherBytes.initial), GetParam().decryptedInitialByte);
|
folly::hexlify(cipherBytes.initial), GetParam().decryptedInitialByte);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
|
@ -25,7 +25,9 @@ mvfst_cpp_library(
|
|||||||
],
|
],
|
||||||
exported_deps = [
|
exported_deps = [
|
||||||
":aead",
|
":aead",
|
||||||
|
"//folly:expected",
|
||||||
"//quic:constants",
|
"//quic:constants",
|
||||||
|
"//quic:exception",
|
||||||
"//quic/codec:packet_number_cipher",
|
"//quic/codec:packet_number_cipher",
|
||||||
"//quic/codec:types",
|
"//quic/codec:types",
|
||||||
],
|
],
|
||||||
@ -44,6 +46,7 @@ mvfst_cpp_library(
|
|||||||
"//quic/state:quic_state_machine",
|
"//quic/state:quic_state_machine",
|
||||||
],
|
],
|
||||||
exported_deps = [
|
exported_deps = [
|
||||||
|
"//folly:expected",
|
||||||
"//quic:constants",
|
"//quic:constants",
|
||||||
"//quic:exception",
|
"//quic:exception",
|
||||||
"//quic/codec:types",
|
"//quic/codec:types",
|
||||||
|
@ -8,7 +8,10 @@ mvfst_cpp_library(
|
|||||||
"Mocks.h",
|
"Mocks.h",
|
||||||
],
|
],
|
||||||
exported_deps = [
|
exported_deps = [
|
||||||
|
"//folly:expected",
|
||||||
|
"//folly:unit",
|
||||||
"//folly/portability:gmock",
|
"//folly/portability:gmock",
|
||||||
|
"//quic:exception",
|
||||||
"//quic/codec:packet_number_cipher",
|
"//quic/codec:packet_number_cipher",
|
||||||
"//quic/fizz/handshake:fizz_handshake",
|
"//quic/fizz/handshake:fizz_handshake",
|
||||||
"//quic/handshake:aead",
|
"//quic/handshake:aead",
|
||||||
|
@ -7,7 +7,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <folly/Expected.h>
|
||||||
|
#include <folly/Unit.h>
|
||||||
#include <folly/portability/GMock.h>
|
#include <folly/portability/GMock.h>
|
||||||
|
#include <quic/QuicException.h>
|
||||||
#include <quic/codec/PacketNumberCipher.h>
|
#include <quic/codec/PacketNumberCipher.h>
|
||||||
#include <quic/fizz/handshake/FizzCryptoFactory.h>
|
#include <quic/fizz/handshake/FizzCryptoFactory.h>
|
||||||
#include <quic/handshake/Aead.h>
|
#include <quic/handshake/Aead.h>
|
||||||
@ -23,8 +26,15 @@ class MockPacketNumberCipher : public PacketNumberCipher {
|
|||||||
public:
|
public:
|
||||||
virtual ~MockPacketNumberCipher() = default;
|
virtual ~MockPacketNumberCipher() = default;
|
||||||
|
|
||||||
MOCK_METHOD(void, setKey, (ByteRange key));
|
MOCK_METHOD(
|
||||||
MOCK_METHOD(HeaderProtectionMask, mask, (ByteRange), (const));
|
(folly::Expected<folly::Unit, QuicError>),
|
||||||
|
setKey,
|
||||||
|
(ByteRange key));
|
||||||
|
MOCK_METHOD(
|
||||||
|
(folly::Expected<HeaderProtectionMask, QuicError>),
|
||||||
|
mask,
|
||||||
|
(ByteRange),
|
||||||
|
(const));
|
||||||
MOCK_METHOD(size_t, keyLength, (), (const));
|
MOCK_METHOD(size_t, keyLength, (), (const));
|
||||||
MOCK_METHOD(const BufPtr&, getKey, (), (const));
|
MOCK_METHOD(const BufPtr&, getKey, (), (const));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user