Skip to content

Commit

Permalink
Fix connection mishandling out of order initial packets with retrys (m…
Browse files Browse the repository at this point in the history
  • Loading branch information
thhous-msft authored Dec 2, 2021
1 parent 04a6c3f commit e48a14f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 44 deletions.
41 changes: 1 addition & 40 deletions src/core/binding.c
Original file line number Diff line number Diff line change
Expand Up @@ -1211,45 +1211,6 @@ QuicBindingPreprocessDatagram(
return TRUE;
}

//
// Returns TRUE if the retry token was successfully decrypted and validated.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicBindingValidateRetryToken(
_In_ const QUIC_BINDING* const Binding,
_In_ const CXPLAT_RECV_PACKET* const Packet,
_In_ uint16_t TokenLength,
_In_reads_(TokenLength)
const uint8_t* TokenBuffer
)
{
if (TokenLength != sizeof(QUIC_RETRY_TOKEN_CONTENTS)) {
QuicPacketLogDrop(Binding, Packet, "Invalid Retry Token Length");
return FALSE;
}

QUIC_RETRY_TOKEN_CONTENTS Token;
if (!QuicRetryTokenDecrypt(Packet, TokenBuffer, &Token)) {
QuicPacketLogDrop(Binding, Packet, "Retry Token Decryption Failure");
return FALSE;
}

if (Token.Encrypted.OrigConnIdLength > sizeof(Token.Encrypted.OrigConnId)) {
QuicPacketLogDrop(Binding, Packet, "Invalid Retry Token OrigConnId Length");
return FALSE;
}

const CXPLAT_RECV_DATA* Datagram =
CxPlatDataPathRecvPacketToRecvData(Packet);
if (!QuicAddrCompare(&Token.Encrypted.RemoteAddress, &Datagram->Route->RemoteAddress)) {
QuicPacketLogDrop(Binding, Packet, "Retry Token Addr Mismatch");
return FALSE;
}

return TRUE;
}

//
// Returns TRUE if we should respond to the connection attempt with a Retry
// packet.
Expand Down Expand Up @@ -1277,7 +1238,7 @@ QuicBindingShouldRetryConnection(
//
// Must always validate the token when provided by the client.
//
if (QuicBindingValidateRetryToken(Binding, Packet, TokenLength, Token)) {
if (QuicPacketValidateRetryToken(Binding, Packet, TokenLength, Token)) {
Packet->ValidToken = TRUE;
} else {
*DropPacket = TRUE;
Expand Down
20 changes: 16 additions & 4 deletions src/core/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -3519,10 +3519,23 @@ QuicConnRecvHeader(
}

QUIC_PATH* Path = &Connection->Paths[0];
if (!Path->IsPeerValidated && Packet->ValidToken) {
if (!Path->IsPeerValidated && (Packet->ValidToken || TokenLength != 0)) {

if (Packet->ValidToken) {
CXPLAT_DBG_ASSERT(TokenBuffer == NULL);
CXPLAT_DBG_ASSERT(TokenLength == 0);
QuicPacketDecodeRetryTokenV1(Packet, &TokenBuffer, &TokenLength);
} else {
CXPLAT_DBG_ASSERT(TokenBuffer != NULL);
if (!QuicPacketValidateRetryToken(
Connection,
Packet,
TokenLength,
TokenBuffer)) {
return FALSE;
}
}

CXPLAT_DBG_ASSERT(TokenBuffer == NULL);
QuicPacketDecodeRetryTokenV1(Packet, &TokenBuffer, &TokenLength);
CXPLAT_DBG_ASSERT(TokenBuffer != NULL);
CXPLAT_DBG_ASSERT(TokenLength == sizeof(QUIC_RETRY_TOKEN_CONTENTS));

Expand Down Expand Up @@ -3581,7 +3594,6 @@ QuicConnRecvHeader(
Connection->OrigDestCID->Data,
Packet->DestCid,
Packet->DestCidLen);

}

Packet->KeyType = QuicPacketTypeToKeyType(Packet->LH->Type);
Expand Down
39 changes: 39 additions & 0 deletions src/core/packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,45 @@ QuicPacketDecodeRetryTokenV1(
*TokenLength = (uint16_t)TokenLengthVarInt;
}

//
// Returns TRUE if the retry token was successfully decrypted and validated.
//
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicPacketValidateRetryToken(
_In_ const void* const Owner,
_In_ const CXPLAT_RECV_PACKET* const Packet,
_In_ uint16_t TokenLength,
_In_reads_(TokenLength)
const uint8_t* TokenBuffer
)
{
if (TokenLength != sizeof(QUIC_RETRY_TOKEN_CONTENTS)) {
QuicPacketLogDrop(Owner, Packet, "Invalid Retry Token Length");
return FALSE;
}

QUIC_RETRY_TOKEN_CONTENTS Token;
if (!QuicRetryTokenDecrypt(Packet, TokenBuffer, &Token)) {
QuicPacketLogDrop(Owner, Packet, "Retry Token Decryption Failure");
return FALSE;
}

if (Token.Encrypted.OrigConnIdLength > sizeof(Token.Encrypted.OrigConnId)) {
QuicPacketLogDrop(Owner, Packet, "Invalid Retry Token OrigConnId Length");
return FALSE;
}

const CXPLAT_RECV_DATA* Datagram =
CxPlatDataPathRecvPacketToRecvData(Packet);
if (!QuicAddrCompare(&Token.Encrypted.RemoteAddress, &Datagram->Route->RemoteAddress)) {
QuicPacketLogDrop(Owner, Packet, "Retry Token Addr Mismatch");
return FALSE;
}

return TRUE;
}

_IRQL_requires_max_(DISPATCH_LEVEL)
_Success_(return != FALSE)
BOOLEAN
Expand Down
10 changes: 10 additions & 0 deletions src/core/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,16 @@ QuicPacketDecodeRetryTokenV1(
_Out_ uint16_t* TokenLength
);

_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
QuicPacketValidateRetryToken(
_In_ const void* const Owner,
_In_ const CXPLAT_RECV_PACKET* const Packet,
_In_ uint16_t TokenLength,
_In_reads_(TokenLength)
const uint8_t* TokenBuffer
);

_IRQL_requires_max_(DISPATCH_LEVEL)
_Success_(return != FALSE)
BOOLEAN
Expand Down

0 comments on commit e48a14f

Please sign in to comment.