Index: net/quic/quic_framer.cc |
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc |
index 1dd0064570b6edccdbd930e8ddf5a997dee0a311..852114a0c245104ab511b6e8578eafd540b6119a 100644 |
--- a/net/quic/quic_framer.cc |
+++ b/net/quic/quic_framer.cc |
@@ -39,9 +39,6 @@ const QuicPacketNumber k4ByteSequenceNumberMask = UINT64_C(0x00000000FFFFFFFF); |
const QuicPacketNumber k2ByteSequenceNumberMask = UINT64_C(0x000000000000FFFF); |
const QuicPacketNumber k1ByteSequenceNumberMask = UINT64_C(0x00000000000000FF); |
-const QuicConnectionId k1ByteConnectionIdMask = UINT64_C(0x00000000000000FF); |
-const QuicConnectionId k4ByteConnectionIdMask = UINT64_C(0x00000000FFFFFFFF); |
- |
// Number of bits the packet number length bits are shifted from the right |
// edge of the public header. |
const uint8_t kPublicHeaderSequenceNumberShift = 4; |
@@ -653,6 +650,11 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header, |
GetSequenceNumberFlags(header.public_header.packet_number_length) |
<< kPublicHeaderSequenceNumberShift; |
+ if (header.public_header.nonce != nullptr) { |
+ DCHECK_EQ(Perspective::IS_SERVER, perspective_); |
+ public_flags |= PACKET_PUBLIC_FLAGS_NONCE; |
+ } |
+ |
switch (header.public_header.connection_id_length) { |
case PACKET_0BYTE_CONNECTION_ID: |
if (!writer->WriteUInt8(public_flags | |
@@ -660,32 +662,14 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header, |
return false; |
} |
break; |
- case PACKET_1BYTE_CONNECTION_ID: |
- if (!writer->WriteUInt8(public_flags | |
- PACKET_PUBLIC_FLAGS_1BYTE_CONNECTION_ID)) { |
- return false; |
- } |
- if (!writer->WriteUInt8(header.public_header.connection_id & |
- k1ByteConnectionIdMask)) { |
- return false; |
- } |
- break; |
- case PACKET_4BYTE_CONNECTION_ID: |
- if (!writer->WriteUInt8(public_flags | |
- PACKET_PUBLIC_FLAGS_4BYTE_CONNECTION_ID)) { |
- return false; |
- } |
- if (!writer->WriteUInt32(header.public_header.connection_id & |
- k4ByteConnectionIdMask)) { |
- return false; |
- } |
- break; |
case PACKET_8BYTE_CONNECTION_ID: |
- if (!writer->WriteUInt8(public_flags | |
- PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID)) { |
- return false; |
+ if (quic_version_ > QUIC_VERSION_32) { |
+ public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID; |
+ } else { |
+ public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD; |
} |
- if (!writer->WriteUInt64(header.public_header.connection_id)) { |
+ if (!writer->WriteUInt8(public_flags) || |
+ !writer->WriteUInt64(header.public_header.connection_id)) { |
return false; |
} |
break; |
@@ -705,6 +689,12 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header, |
return false; |
} |
+ if (header.public_header.nonce != nullptr && |
+ !writer->WriteBytes(header.public_header.nonce, |
+ kDiversificationNonceSize)) { |
+ return false; |
+ } |
+ |
if (!AppendPacketSequenceNumber(header.public_header.packet_number_length, |
header.packet_number, writer)) { |
return false; |
@@ -827,42 +817,6 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader, |
} |
public_header->connection_id_length = PACKET_8BYTE_CONNECTION_ID; |
break; |
- case PACKET_PUBLIC_FLAGS_4BYTE_CONNECTION_ID: |
- // If the connection_id is truncated, expect to read the last serialized |
- // connection_id. |
- if (!reader->ReadBytes(&public_header->connection_id, |
- PACKET_4BYTE_CONNECTION_ID)) { |
- set_detailed_error("Unable to read ConnectionId."); |
- return false; |
- } |
- if (last_serialized_connection_id_ && |
- (public_header->connection_id & k4ByteConnectionIdMask) != |
- (last_serialized_connection_id_ & k4ByteConnectionIdMask)) { |
- set_detailed_error( |
- "Truncated 4 byte ConnectionId does not match " |
- "previous connection_id."); |
- return false; |
- } |
- public_header->connection_id_length = PACKET_4BYTE_CONNECTION_ID; |
- public_header->connection_id = last_serialized_connection_id_; |
- break; |
- case PACKET_PUBLIC_FLAGS_1BYTE_CONNECTION_ID: |
- if (!reader->ReadBytes(&public_header->connection_id, |
- PACKET_1BYTE_CONNECTION_ID)) { |
- set_detailed_error("Unable to read ConnectionId."); |
- return false; |
- } |
- if (last_serialized_connection_id_ && |
- (public_header->connection_id & k1ByteConnectionIdMask) != |
- (last_serialized_connection_id_ & k1ByteConnectionIdMask)) { |
- set_detailed_error( |
- "Truncated 1 byte ConnectionId does not match " |
- "previous connection_id."); |
- return false; |
- } |
- public_header->connection_id_length = PACKET_1BYTE_CONNECTION_ID; |
- public_header->connection_id = last_serialized_connection_id_; |
- break; |
case PACKET_PUBLIC_FLAGS_0BYTE_CONNECTION_ID: |
public_header->connection_id_length = PACKET_0BYTE_CONNECTION_ID; |
public_header->connection_id = last_serialized_connection_id_; |
@@ -892,6 +846,26 @@ bool QuicFramer::ProcessPublicHeader(QuicDataReader* reader, |
} |
public_header->versions.push_back(version); |
} |
+ |
+ // A nonce should only be present in packets from the server to the client, |
+ // and only for versions after QUIC_VERSION_32. Earlier versions will |
+ // set this bit when indicating an 8-byte connection ID, which should |
+ // not be interpreted as indicating a nonce is present. |
+ if (quic_version_ > QUIC_VERSION_32 && |
+ public_flags & PACKET_PUBLIC_FLAGS_NONCE && |
+ // The nonce flag from a client is ignored and is assumed to be an older |
+ // client indicating an eight-byte connection ID. |
+ perspective_ == Perspective::IS_CLIENT) { |
+ if (!reader->ReadBytes(reinterpret_cast<uint8_t*>(last_nonce_), |
+ sizeof(last_nonce_))) { |
+ set_detailed_error("Unable to read nonce."); |
+ return false; |
+ } |
+ public_header->nonce = &last_nonce_; |
+ } else { |
+ public_header->nonce = nullptr; |
+ } |
+ |
return true; |
} |
@@ -1615,12 +1589,14 @@ StringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket( |
QuicConnectionIdLength connection_id_length, |
bool includes_version, |
bool includes_path_id, |
+ bool includes_diversification_nonce, |
QuicPacketNumberLength packet_number_length) { |
// TODO(ianswett): This is identical to QuicData::AssociatedData. |
return StringPiece( |
encrypted.data(), |
GetStartOfEncryptedData(connection_id_length, includes_version, |
- includes_path_id, packet_number_length)); |
+ includes_path_id, includes_diversification_nonce, |
+ packet_number_length)); |
} |
void QuicFramer::SetDecrypter(EncryptionLevel level, QuicDecrypter* decrypter) { |
@@ -1726,13 +1702,29 @@ bool QuicFramer::DecryptPayload(QuicDataReader* encrypted_reader, |
StringPiece associated_data = GetAssociatedDataFromEncryptedPacket( |
packet, header.public_header.connection_id_length, |
header.public_header.version_flag, header.public_header.multipath_flag, |
+ header.public_header.nonce != nullptr, |
header.public_header.packet_number_length); |
+ |
bool success = decrypter_->DecryptPacket( |
header.path_id, header.packet_number, associated_data, encrypted, |
decrypted_buffer, decrypted_length, buffer_length); |
if (success) { |
visitor_->OnDecryptedPacket(decrypter_level_); |
} else if (alternative_decrypter_.get() != nullptr) { |
+ if (header.public_header.nonce != nullptr) { |
+ DCHECK_EQ(perspective_, Perspective::IS_CLIENT); |
+ alternative_decrypter_->SetDiversificationNonce( |
+ *header.public_header.nonce); |
+ } |
+ if (alternative_decrypter_level_ == ENCRYPTION_INITIAL) { |
+ if (perspective_ == Perspective::IS_CLIENT && |
+ quic_version_ > QUIC_VERSION_32) { |
+ DCHECK(header.public_header.nonce != nullptr); |
+ } else { |
+ DCHECK(header.public_header.nonce == nullptr); |
+ } |
+ } |
+ |
success = alternative_decrypter_->DecryptPacket( |
header.path_id, header.packet_number, associated_data, encrypted, |
decrypted_buffer, decrypted_length, buffer_length); |