mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-06 22:22:38 +03:00
Implement an explicit inplace encrypt in Aead.
Summary: This is useful when you want to ensure that the IOBuf you pass in is encrypted inplace, as opposed to potentially creating a new one. Reviewed By: yangchi Differential Revision: D21135253 fbshipit-source-id: 89b6e718fc8da1324685c390c721a564bb77d01d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c62d0877d1
commit
524bf84c44
@@ -204,8 +204,8 @@ DataPathResult iobufChainBasedBuildScheduleEncrypt(
|
|||||||
bodyCursor.pull(unencrypted->writableData() + headerLen, bodyLen);
|
bodyCursor.pull(unencrypted->writableData() + headerLen, bodyLen);
|
||||||
unencrypted->advance(headerLen);
|
unencrypted->advance(headerLen);
|
||||||
unencrypted->append(bodyLen);
|
unencrypted->append(bodyLen);
|
||||||
auto packetBuf =
|
auto packetBuf = aead.inplaceEncrypt(
|
||||||
aead.encrypt(std::move(unencrypted), packet->header.get(), packetNum);
|
std::move(unencrypted), packet->header.get(), packetNum);
|
||||||
DCHECK(packetBuf->headroom() == headerLen);
|
DCHECK(packetBuf->headroom() == headerLen);
|
||||||
packetBuf->clear();
|
packetBuf->clear();
|
||||||
auto headerCursor = folly::io::Cursor(packet->header.get());
|
auto headerCursor = folly::io::Cursor(packet->header.get());
|
||||||
@@ -832,8 +832,8 @@ void writeCloseCommon(
|
|||||||
}
|
}
|
||||||
auto packet = std::move(packetBuilder).buildPacket();
|
auto packet = std::move(packetBuilder).buildPacket();
|
||||||
packet.header->coalesce();
|
packet.header->coalesce();
|
||||||
auto body =
|
auto body = aead.inplaceEncrypt(
|
||||||
aead.encrypt(std::move(packet.body), packet.header.get(), packetNum);
|
std::move(packet.body), packet.header.get(), packetNum);
|
||||||
body->coalesce();
|
body->coalesce();
|
||||||
encryptPacketHeader(
|
encryptPacketHeader(
|
||||||
headerForm,
|
headerForm,
|
||||||
|
@@ -1402,7 +1402,7 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingOldData) {
|
|||||||
writeDataToQuicStream(*stream, buf->clone(), true);
|
writeDataToQuicStream(*stream, buf->clone(), true);
|
||||||
|
|
||||||
folly::IOBuf pktBodyCaptured;
|
folly::IOBuf pktBodyCaptured;
|
||||||
EXPECT_CALL(*capturingAead, _encrypt(_, _, _))
|
EXPECT_CALL(*capturingAead, _inplaceEncrypt(_, _, _))
|
||||||
.WillRepeatedly(Invoke([&](auto& buf, auto, auto) {
|
.WillRepeatedly(Invoke([&](auto& buf, auto, auto) {
|
||||||
if (buf) {
|
if (buf) {
|
||||||
pktBodyCaptured.prependChain(buf->clone());
|
pktBodyCaptured.prependChain(buf->clone());
|
||||||
@@ -1418,7 +1418,7 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingOldData) {
|
|||||||
// Now we have no new data, let's probe again, and verify the same old data is
|
// Now we have no new data, let's probe again, and verify the same old data is
|
||||||
// sent.
|
// sent.
|
||||||
folly::IOBuf secondBodyCaptured;
|
folly::IOBuf secondBodyCaptured;
|
||||||
EXPECT_CALL(*capturingAead, _encrypt(_, _, _))
|
EXPECT_CALL(*capturingAead, _inplaceEncrypt(_, _, _))
|
||||||
.WillRepeatedly(Invoke([&](auto& buf, auto, auto) {
|
.WillRepeatedly(Invoke([&](auto& buf, auto, auto) {
|
||||||
if (buf) {
|
if (buf) {
|
||||||
secondBodyCaptured.prependChain(buf->clone());
|
secondBodyCaptured.prependChain(buf->clone());
|
||||||
|
@@ -186,7 +186,7 @@ class QuicTransportTest : public Test {
|
|||||||
// a cipher.
|
// a cipher.
|
||||||
auto aead = std::make_unique<NiceMock<MockAead>>();
|
auto aead = std::make_unique<NiceMock<MockAead>>();
|
||||||
aead_ = aead.get();
|
aead_ = aead.get();
|
||||||
EXPECT_CALL(*aead_, _encrypt(_, _, _))
|
EXPECT_CALL(*aead_, _inplaceEncrypt(_, _, _))
|
||||||
.WillRepeatedly(
|
.WillRepeatedly(
|
||||||
Invoke([&](auto& buf, auto, auto) { return buf->clone(); }));
|
Invoke([&](auto& buf, auto, auto) { return buf->clone(); }));
|
||||||
EXPECT_CALL(*aead_, _decrypt(_, _, _))
|
EXPECT_CALL(*aead_, _decrypt(_, _, _))
|
||||||
|
@@ -163,12 +163,11 @@ bool ClientHandshake::verifyRetryIntegrityTag(
|
|||||||
retryPacket.header.getToken().size());
|
retryPacket.header.getToken().size());
|
||||||
|
|
||||||
pseudoRetryPacket.coalesce();
|
pseudoRetryPacket.coalesce();
|
||||||
std::unique_ptr<folly::IOBuf> emptyPlaintext =
|
|
||||||
std::make_unique<folly::IOBuf>();
|
|
||||||
|
|
||||||
auto retryCipher = getRetryPacketCipher();
|
auto retryCipher = getRetryPacketCipher();
|
||||||
auto expectedIntegrityTag =
|
auto emptyPlaintext = folly::IOBuf::create(retryCipher->getCipherOverhead());
|
||||||
retryCipher->encrypt(std::move(emptyPlaintext), &pseudoRetryPacket, 0);
|
auto expectedIntegrityTag = retryCipher->inplaceEncrypt(
|
||||||
|
std::move(emptyPlaintext), &pseudoRetryPacket, 0);
|
||||||
|
|
||||||
return folly::IOBufEqualTo()(
|
return folly::IOBufEqualTo()(
|
||||||
*expectedIntegrityTag, *retryPacket.integrityTag);
|
*expectedIntegrityTag, *retryPacket.integrityTag);
|
||||||
|
@@ -75,7 +75,7 @@ Buf packetToBuf(
|
|||||||
}
|
}
|
||||||
if (aead && packet.header) {
|
if (aead && packet.header) {
|
||||||
auto bodySize = body->computeChainDataLength();
|
auto bodySize = body->computeChainDataLength();
|
||||||
body = aead->encrypt(std::move(body), packet.header.get(), num);
|
body = aead->inplaceEncrypt(std::move(body), packet.header.get(), num);
|
||||||
EXPECT_GT(body->computeChainDataLength(), bodySize);
|
EXPECT_GT(body->computeChainDataLength(), bodySize);
|
||||||
}
|
}
|
||||||
if (body) {
|
if (body) {
|
||||||
|
@@ -265,10 +265,10 @@ template <class T>
|
|||||||
std::unique_ptr<T> createNoOpAeadImpl() {
|
std::unique_ptr<T> createNoOpAeadImpl() {
|
||||||
// Fake that the handshake has already occured
|
// Fake that the handshake has already occured
|
||||||
auto aead = std::make_unique<NiceMock<T>>();
|
auto aead = std::make_unique<NiceMock<T>>();
|
||||||
ON_CALL(*aead, _encrypt(_, _, _))
|
ON_CALL(*aead, _inplaceEncrypt(_, _, _))
|
||||||
.WillByDefault(Invoke([&](auto& buf, auto, auto) {
|
.WillByDefault(Invoke([&](auto& buf, auto, auto) {
|
||||||
if (buf) {
|
if (buf) {
|
||||||
return buf->clone();
|
return std::move(buf);
|
||||||
} else {
|
} else {
|
||||||
return folly::IOBuf::create(0);
|
return folly::IOBuf::create(0);
|
||||||
}
|
}
|
||||||
@@ -426,12 +426,20 @@ Buf packetToBufCleartext(
|
|||||||
auto packetBuf = packet.header->clone();
|
auto packetBuf = packet.header->clone();
|
||||||
Buf body;
|
Buf body;
|
||||||
if (packet.body) {
|
if (packet.body) {
|
||||||
|
packet.body->coalesce();
|
||||||
body = packet.body->clone();
|
body = packet.body->clone();
|
||||||
|
} else {
|
||||||
|
body = folly::IOBuf::create(0);
|
||||||
}
|
}
|
||||||
auto headerForm = packet.packet.header.getHeaderForm();
|
auto headerForm = packet.packet.header.getHeaderForm();
|
||||||
packet.header->coalesce();
|
packet.header->coalesce();
|
||||||
auto encryptedBody =
|
auto tagLen = cleartextCipher.getCipherOverhead();
|
||||||
cleartextCipher.encrypt(std::move(body), packet.header.get(), packetNum);
|
if (body->tailroom() < tagLen) {
|
||||||
|
body->prependChain(folly::IOBuf::create(tagLen));
|
||||||
|
}
|
||||||
|
body->coalesce();
|
||||||
|
auto encryptedBody = cleartextCipher.inplaceEncrypt(
|
||||||
|
std::move(body), packet.header.get(), packetNum);
|
||||||
encryptedBody->coalesce();
|
encryptedBody->coalesce();
|
||||||
encryptPacketHeader(
|
encryptPacketHeader(
|
||||||
headerForm,
|
headerForm,
|
||||||
|
@@ -32,11 +32,12 @@ class FizzAead final : public Aead {
|
|||||||
/**
|
/**
|
||||||
* Simply forward all calls to fizz::Aead.
|
* Simply forward all calls to fizz::Aead.
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<folly::IOBuf> encrypt(
|
std::unique_ptr<folly::IOBuf> inplaceEncrypt(
|
||||||
std::unique_ptr<folly::IOBuf>&& plaintext,
|
std::unique_ptr<folly::IOBuf>&& plaintext,
|
||||||
const folly::IOBuf* associatedData,
|
const folly::IOBuf* associatedData,
|
||||||
uint64_t seqNum) const override {
|
uint64_t seqNum) const override {
|
||||||
return fizzAead->encrypt(std::move(plaintext), associatedData, seqNum);
|
return fizzAead->inplaceEncrypt(
|
||||||
|
std::move(plaintext), associatedData, seqNum);
|
||||||
}
|
}
|
||||||
std::unique_ptr<folly::IOBuf> decrypt(
|
std::unique_ptr<folly::IOBuf> decrypt(
|
||||||
std::unique_ptr<folly::IOBuf>&& ciphertext,
|
std::unique_ptr<folly::IOBuf>&& ciphertext,
|
||||||
|
@@ -26,9 +26,9 @@ class Aead {
|
|||||||
virtual ~Aead() = default;
|
virtual ~Aead() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encrypts plaintext. Will throw on error.
|
* Encrypts plaintext inplace. Will throw on error.
|
||||||
*/
|
*/
|
||||||
virtual std::unique_ptr<folly::IOBuf> encrypt(
|
virtual std::unique_ptr<folly::IOBuf> inplaceEncrypt(
|
||||||
std::unique_ptr<folly::IOBuf>&& plaintext,
|
std::unique_ptr<folly::IOBuf>&& plaintext,
|
||||||
const folly::IOBuf* associatedData,
|
const folly::IOBuf* associatedData,
|
||||||
uint64_t seqNum) const = 0;
|
uint64_t seqNum) const = 0;
|
||||||
|
@@ -32,16 +32,16 @@ class MockAead : public Aead {
|
|||||||
MOCK_CONST_METHOD0(getCipherOverhead, size_t());
|
MOCK_CONST_METHOD0(getCipherOverhead, size_t());
|
||||||
|
|
||||||
MOCK_CONST_METHOD3(
|
MOCK_CONST_METHOD3(
|
||||||
_encrypt,
|
_inplaceEncrypt,
|
||||||
std::unique_ptr<folly::IOBuf>(
|
std::unique_ptr<folly::IOBuf>(
|
||||||
std::unique_ptr<folly::IOBuf>& plaintext,
|
std::unique_ptr<folly::IOBuf>& plaintext,
|
||||||
const folly::IOBuf* associatedData,
|
const folly::IOBuf* associatedData,
|
||||||
uint64_t seqNum));
|
uint64_t seqNum));
|
||||||
std::unique_ptr<folly::IOBuf> encrypt(
|
std::unique_ptr<folly::IOBuf> inplaceEncrypt(
|
||||||
std::unique_ptr<folly::IOBuf>&& plaintext,
|
std::unique_ptr<folly::IOBuf>&& plaintext,
|
||||||
const folly::IOBuf* associatedData,
|
const folly::IOBuf* associatedData,
|
||||||
uint64_t seqNum) const override {
|
uint64_t seqNum) const override {
|
||||||
return _encrypt(plaintext, associatedData, seqNum);
|
return _inplaceEncrypt(plaintext, associatedData, seqNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
MOCK_CONST_METHOD3(
|
MOCK_CONST_METHOD3(
|
||||||
@@ -71,9 +71,9 @@ class MockAead : public Aead {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setDefaults() {
|
void setDefaults() {
|
||||||
ON_CALL(*this, _encrypt(_, _, _)).WillByDefault(InvokeWithoutArgs([]() {
|
ON_CALL(*this, _inplaceEncrypt(_, _, _))
|
||||||
return folly::IOBuf::copyBuffer("ciphertext");
|
.WillByDefault(InvokeWithoutArgs(
|
||||||
}));
|
[]() { return folly::IOBuf::copyBuffer("ciphertext"); }));
|
||||||
ON_CALL(*this, _decrypt(_, _, _)).WillByDefault(InvokeWithoutArgs([]() {
|
ON_CALL(*this, _decrypt(_, _, _)).WillByDefault(InvokeWithoutArgs([]() {
|
||||||
return folly::IOBuf::copyBuffer("plaintext");
|
return folly::IOBuf::copyBuffer("plaintext");
|
||||||
}));
|
}));
|
||||||
|
Reference in New Issue
Block a user