Skip to content

Commit

Permalink
Version Negotiation Extension v4 (microsoft#1826)
Browse files Browse the repository at this point in the history
  • Loading branch information
anrossi authored Jul 22, 2021
1 parent acdebe4 commit 7cafdc4
Show file tree
Hide file tree
Showing 14 changed files with 559 additions and 1,063 deletions.
254 changes: 152 additions & 102 deletions src/core/connection.c

Large diffs are not rendered by default.

25 changes: 18 additions & 7 deletions src/core/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ typedef struct QUIC_LISTENER QUIC_LISTENER;
// Note - Keep quictypes.h's copy up to date.
//
typedef union QUIC_CONNECTION_STATE {
uint32_t Flags;
uint64_t Flags;
struct {
BOOLEAN Allocated : 1; // Allocated. Used for Debugging.
BOOLEAN Initialized : 1; // Initialized successfully. Used for Debugging.
Expand Down Expand Up @@ -159,6 +159,17 @@ typedef union QUIC_CONNECTION_STATE {
//
BOOLEAN InlineApiExecution : 1;

//
// True when a server attempts Compatible Version Negotiation
BOOLEAN CompatibleVerNegotiationAttempted : 1;

//
// True once a client connection has completed a compatible version
// negotiation, and false otherwise. Used to prevent packets with invalid
// version fields from being accepted.
//
BOOLEAN CompatibleVerNegotiationCompleted : 1;

#ifdef CxPlatVerifierEnabledByAddr
//
// The calling app is being verified (app or driver verifier).
Expand All @@ -168,7 +179,7 @@ typedef union QUIC_CONNECTION_STATE {
};
} QUIC_CONNECTION_STATE;

CXPLAT_STATIC_ASSERT(sizeof(QUIC_CONNECTION_STATE) == sizeof(uint32_t), "Ensure correct size/type");
CXPLAT_STATIC_ASSERT(sizeof(QUIC_CONNECTION_STATE) == sizeof(uint64_t), "Ensure correct size/type");

//
// Different references on a connection.
Expand Down Expand Up @@ -571,15 +582,15 @@ typedef struct QUIC_CONNECTION {
#endif

//
// Received version negotiation list from a previous connection attempt.
// Previously-attempted QUIC version, after Incompatible Version Negotiation.
//
const uint32_t* ReceivedNegotiationVersions;
uint32_t ReceivedNegotiationVersionsLength;
uint32_t PreviousQuicVersion;

//
// Previously-attempted QUIC version.
// Initially-attempted QUIC version.
// Only populated during compatible version negotiation.
//
uint32_t PreviousQuicVersion;
uint32_t OriginalQuicVersion;

//
// The size of the keep alive padding.
Expand Down
48 changes: 24 additions & 24 deletions src/core/crypto_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ typedef enum eSniNameType {
//
// Extensions
//
#define QUIC_TP_ID_MAX_DATAGRAM_FRAME_SIZE 32 // varint
#define QUIC_TP_ID_DISABLE_1RTT_ENCRYPTION 0xBAAD // N/A
#define QUIC_TP_ID_VERSION_NEGOTIATION_EXT 0x73DB // Blob
#define QUIC_TP_ID_MIN_ACK_DELAY 0xFF02DE1AULL // varint
#define QUIC_TP_ID_MAX_DATAGRAM_FRAME_SIZE 32 // varint
#define QUIC_TP_ID_DISABLE_1RTT_ENCRYPTION 0xBAAD // N/A
#define QUIC_TP_ID_VERSION_NEGOTIATION_EXT 0xFF73DB // Blob
#define QUIC_TP_ID_MIN_ACK_DELAY 0xFF02DE1AULL // varint

BOOLEAN
QuicTpIdIsReserved(
Expand Down Expand Up @@ -817,7 +817,7 @@ QuicCryptoTlsEncodeTransportParameters(
RequiredTPLen += (size_t)
TlsTransportParamLength(
QUIC_TP_ID_VERSION_NEGOTIATION_EXT,
TransportParams->VersionNegotiationInfoLength);
TransportParams->VersionInfoLength);
}
if (TransportParams->Flags & QUIC_TP_FLAG_MIN_ACK_DELAY) {
CXPLAT_DBG_ASSERT(
Expand Down Expand Up @@ -1097,14 +1097,14 @@ QuicCryptoTlsEncodeTransportParameters(
TPBuf =
TlsWriteTransportParam(
QUIC_TP_ID_VERSION_NEGOTIATION_EXT,
(uint16_t)TransportParams->VersionNegotiationInfoLength,
TransportParams->VersionNegotiationInfo,
(uint16_t)TransportParams->VersionInfoLength,
TransportParams->VersionInfo,
TPBuf);
QuicTraceLogConnVerbose(
EncodeTPVersionNegotiationExt,
Connection,
"TP: Version Negotiation Extension (%llu bytes)",
TransportParams->VersionNegotiationInfoLength);
"TP: Version Negotiation Extension (%u bytes)",
TransportParams->VersionInfoLength);
}
if (TransportParams->Flags & QUIC_TP_FLAG_MIN_ACK_DELAY) {
TPBuf =
Expand Down Expand Up @@ -1694,8 +1694,8 @@ QuicCryptoTlsDecodeTransportParameters(
"Invalid length of QUIC_TP_ID_VERSION_NEGOTIATION_EXT");
goto Exit;
}
TransportParams->VersionNegotiationInfo = CXPLAT_ALLOC_NONPAGED(Length, QUIC_POOL_VER_NEG_INFO);
if (TransportParams->VersionNegotiationInfo == NULL) {
TransportParams->VersionInfo = CXPLAT_ALLOC_NONPAGED(Length, QUIC_POOL_VERSION_INFO);
if (TransportParams->VersionInfo == NULL) {
QuicTraceEvent(
AllocFailure,
"Allocation of '%s' failed. (%llu bytes)",
Expand All @@ -1705,8 +1705,8 @@ QuicCryptoTlsDecodeTransportParameters(
Length);
} else {
TransportParams->Flags |= QUIC_TP_FLAG_VERSION_NEGOTIATION;
CxPlatCopyMemory((uint8_t*)TransportParams->VersionNegotiationInfo, TPBuf + Offset, Length);
TransportParams->VersionNegotiationInfoLength = Length;
CxPlatCopyMemory((uint8_t*)TransportParams->VersionInfo, TPBuf + Offset, Length);
TransportParams->VersionInfoLength = Length;
QuicTraceLogConnVerbose(
DecodeTPVersionNegotiationInfo,
Connection,
Expand Down Expand Up @@ -1789,22 +1789,22 @@ QuicCryptoTlsCopyTransportParameters(
{
*Destination = *Source;
if (Source->Flags & QUIC_TP_FLAG_VERSION_NEGOTIATION) {
Destination->VersionNegotiationInfo =
CXPLAT_ALLOC_NONPAGED((size_t)Source->VersionNegotiationInfoLength, QUIC_POOL_VER_NEG_INFO);
if (Destination->VersionNegotiationInfo == NULL) {
Destination->VersionInfo =
CXPLAT_ALLOC_NONPAGED((size_t)Source->VersionInfoLength, QUIC_POOL_VERSION_INFO);
if (Destination->VersionInfo == NULL) {
QuicTraceEvent(
AllocFailure,
"Allocation of '%s' failed. (%llu bytes)",
"Version Negotiation Info",
Source->VersionNegotiationInfoLength);
Source->VersionInfoLength);
return QUIC_STATUS_OUT_OF_MEMORY;
}
Destination->Flags |= QUIC_TP_FLAG_VERSION_NEGOTIATION;
CxPlatCopyMemory(
(uint8_t*)Destination->VersionNegotiationInfo,
Source->VersionNegotiationInfo,
(size_t)Source->VersionNegotiationInfoLength);
Destination->VersionNegotiationInfoLength = Source->VersionNegotiationInfoLength;
(uint8_t*)Destination->VersionInfo,
Source->VersionInfo,
(size_t)Source->VersionInfoLength);
Destination->VersionInfoLength = Source->VersionInfoLength;
}
return QUIC_STATUS_SUCCESS;
}
Expand All @@ -1816,9 +1816,9 @@ QuicCryptoTlsCleanupTransportParameters(
)
{
if (TransportParams->Flags & QUIC_TP_FLAG_VERSION_NEGOTIATION) {
CXPLAT_FREE(TransportParams->VersionNegotiationInfo, QUIC_POOL_VER_NEG_INFO);
TransportParams->VersionNegotiationInfo = NULL;
TransportParams->VersionNegotiationInfoLength = 0;
CXPLAT_FREE(TransportParams->VersionInfo, QUIC_POOL_VERSION_INFO);
TransportParams->VersionInfo = NULL;
TransportParams->VersionInfoLength = 0;
TransportParams->Flags &= ~QUIC_TP_FLAG_VERSION_NEGOTIATION;
}
}
6 changes: 3 additions & 3 deletions src/core/transport_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ typedef struct QUIC_TRANSPORT_PARAMETERS {
uint8_t RetrySourceConnectionIDLength;

//
// Pointer to the Version Negotiation transport parameter opaque blob.
// The version_information transport parameter opaque blob.
//
const uint8_t* VersionNegotiationInfo;
QUIC_VAR_INT VersionNegotiationInfoLength;
uint32_t VersionInfoLength;
const uint8_t* VersionInfo;

} QUIC_TRANSPORT_PARAMETERS;

Expand Down
10 changes: 5 additions & 5 deletions src/core/unittest/TransportParamTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ void CompareTransportParams(
COMPARE_TP_FIELD(MAX_ACK_DELAY, MaxAckDelay);
COMPARE_TP_FIELD(ACTIVE_CONNECTION_ID_LIMIT, ActiveConnectionIdLimit);
if (A->Flags & QUIC_TP_FLAG_VERSION_NEGOTIATION) {
ASSERT_EQ(A->VersionNegotiationInfoLength, B->VersionNegotiationInfoLength);
ASSERT_EQ(A->VersionInfoLength, B->VersionInfoLength);
ASSERT_EQ(
memcmp(A->VersionNegotiationInfo, B->VersionNegotiationInfo, (size_t)A->VersionNegotiationInfoLength),
memcmp(A->VersionInfo, B->VersionInfo, (size_t)A->VersionInfoLength),
0);
}
//COMPARE_TP_FIELD(InitialSourceConnectionID);
Expand Down Expand Up @@ -136,9 +136,9 @@ TEST(TransportParamTest, VersionNegotiationExtension)
{
QUIC_TRANSPORT_PARAMETERS OriginalTP;
CxPlatZeroMemory(&OriginalTP, sizeof(OriginalTP));
uint8_t VNInfo[21];
OriginalTP.VersionNegotiationInfo = VNInfo;
OriginalTP.VersionNegotiationInfoLength = sizeof(VNInfo);
uint8_t VerInfo[21];
OriginalTP.VersionInfo = VerInfo;
OriginalTP.VersionInfoLength = sizeof(VerInfo);
OriginalTP.Flags = QUIC_TP_FLAG_VERSION_NEGOTIATION;

EncodeDecodeAndCompare(&OriginalTP);
Expand Down
Loading

0 comments on commit 7cafdc4

Please sign in to comment.