1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-07 22:46:22 +03:00

Key update support: Add support for initiating periodic key updates for both client and server [4/x]

Summary:
Allow the server/client transport to initiate periodic key update. It's defaulted to being disabled.

The new logic for initiating and verifying a key update was handled correctly by the peer is consolidated in QuicTransportFunctions.

Reviewed By: mjoras

Differential Revision: D53109624

fbshipit-source-id: 0c3a944978fc0e0a84252da953dc116aa7c26379
This commit is contained in:
Joseph Beshay
2024-02-01 15:41:27 -08:00
committed by Facebook GitHub Bot
parent da3e5e3821
commit aeacf40ae8
14 changed files with 312 additions and 31 deletions

View File

@@ -843,7 +843,20 @@ void updateConnection(
conn.lossState.totalPacketsSent++;
conn.lossState.totalStreamBytesSent += streamBytesSent;
conn.lossState.totalNewStreamBytesSent += newStreamBytesSent;
conn.oneRttWritePacketsSentInCurrentPhase++;
// Count the number of packets sent in the current phase.
// This is used to initiate key updates if enabled.
if (packet.header.getProtectionType() == conn.oneRttWritePhase) {
if (conn.oneRttWritePendingVerification &&
conn.oneRttWritePacketsSentInCurrentPhase == 0) {
// This is the first packet in the new phase after we have initiated a key
// update. We need to keep track of it to confirm the peer acks it in the
// same phase.
conn.oneRttWritePendingVerificationPacketNumber =
packet.header.getPacketSequenceNum();
}
conn.oneRttWritePacketsSentInCurrentPhase++;
}
if (!retransmittable && !isPing) {
DCHECK(!packetEvent);
@@ -1340,7 +1353,7 @@ void writeShortClose(
const Aead& aead,
const PacketNumberCipher& headerCipher) {
auto header = ShortHeader(
ProtectionType::KeyPhaseZero,
connection.oneRttWritePhase,
connId,
getNextPacketNum(connection, PacketNumberSpace::AppData));
writeCloseCommon(
@@ -1919,4 +1932,66 @@ void updateOneRttWriteCipher(
conn.oneRttWritePhase = oneRttPhase;
conn.oneRttWritePacketsSentInCurrentPhase = 0;
}
void maybeHandleIncomingKeyUpdate(QuicConnectionStateBase& conn) {
if (conn.readCodec->getCurrentOneRttReadPhase() != conn.oneRttWritePhase) {
// Peer has initiated a key update.
updateOneRttWriteCipher(
conn,
conn.handshakeLayer->getNextOneRttWriteCipher(),
conn.readCodec->getCurrentOneRttReadPhase());
conn.readCodec->setNextOneRttReadCipher(
conn.handshakeLayer->getNextOneRttReadCipher());
}
}
void maybeInitiateKeyUpdate(QuicConnectionStateBase& conn) {
if (conn.transportSettings.initiateKeyUpdate &&
conn.oneRttWritePacketsSentInCurrentPhase >
conn.transportSettings.keyUpdatePacketCountInterval) {
if (conn.readCodec->canInitiateKeyUpdate()) {
conn.readCodec->advanceOneRttReadPhase();
updateOneRttWriteCipher(
conn,
conn.handshakeLayer->getNextOneRttWriteCipher(),
conn.readCodec->getCurrentOneRttReadPhase());
conn.readCodec->setNextOneRttReadCipher(
conn.handshakeLayer->getNextOneRttReadCipher());
// Signal the transport that a key update has been initiated.
conn.oneRttWritePendingVerification = true;
conn.oneRttWritePendingVerificationPacketNumber.clear();
}
}
}
void maybeVerifyPendingKeyUpdate(
QuicConnectionStateBase& conn,
const OutstandingPacketWrapper& outstandingPacket,
const RegularQuicPacket& ackPacket) {
if (!(protectionTypeToEncryptionLevel(
outstandingPacket.packet.header.getProtectionType()) ==
EncryptionLevel::AppData)) {
// This is not an app data packet. We can't have initiated a key update yet.
return;
}
if (conn.oneRttWritePendingVerificationPacketNumber &&
outstandingPacket.packet.header.getPacketSequenceNum() >=
conn.oneRttWritePendingVerificationPacketNumber.value()) {
// There is a pending key update. This packet should be acked in
// the current phase.
if (ackPacket.header.getProtectionType() == conn.oneRttWritePhase) {
// Key update is verified.
conn.oneRttWritePendingVerificationPacketNumber.clear();
conn.oneRttWritePendingVerification = false;
} else {
throw QuicTransportException(
"Packet with key update was acked in the wrong phase",
TransportErrorCode::CRYPTO_ERROR);
}
}
}
} // namespace quic