diff options
Diffstat (limited to 'net/quic/crypto/crypto_framer.cc')
-rw-r--r-- | net/quic/crypto/crypto_framer.cc | 91 |
1 files changed, 77 insertions, 14 deletions
diff --git a/net/quic/crypto/crypto_framer.cc b/net/quic/crypto/crypto_framer.cc index 4b3ce64..6307d82 100644 --- a/net/quic/crypto/crypto_framer.cc +++ b/net/quic/crypto/crypto_framer.cc @@ -160,26 +160,36 @@ bool CryptoFramer::ProcessInput(StringPiece input) { // static QuicData* CryptoFramer::ConstructHandshakeMessage( const CryptoHandshakeMessage& message) { - if (message.tag_value_map().size() > kMaxEntries) { - return NULL; + size_t num_entries = message.tag_value_map().size(); + size_t pad_length = 0; + bool need_pad_tag = false; + bool need_pad_value = false; + + size_t len = message.size(); + if (len < message.minimum_size()) { + need_pad_tag = true; + need_pad_value = true; + num_entries++; + + size_t delta = message.minimum_size() - len; + const size_t overhead = kQuicTagSize + kCryptoEndOffsetSize; + if (delta > overhead) { + pad_length = delta - overhead; + } + len += overhead + pad_length; } - size_t len = kQuicTagSize; // message tag - len += sizeof(uint16); // number of map entries - len += sizeof(uint16); // padding. - QuicTagValueMap::const_iterator it = message.tag_value_map().begin(); - while (it != message.tag_value_map().end()) { - len += kQuicTagSize; // tag - len += kCryptoEndOffsetSize; // end offset - len += it->second.length(); // value - ++it; + + if (num_entries > kMaxEntries) { + return NULL; } + QuicDataWriter writer(len); if (!writer.WriteUInt32(message.tag())) { DCHECK(false) << "Failed to write message tag."; return NULL; } - if (!writer.WriteUInt16(message.tag_value_map().size())) { + if (!writer.WriteUInt16(num_entries)) { DCHECK(false) << "Failed to write size."; return NULL; } @@ -190,8 +200,23 @@ QuicData* CryptoFramer::ConstructHandshakeMessage( uint32 end_offset = 0; // Tags and offsets - for (it = message.tag_value_map().begin(); + for (QuicTagValueMap::const_iterator it = message.tag_value_map().begin(); it != message.tag_value_map().end(); ++it) { + if (it->first == kPAD && need_pad_tag) { + // Existing PAD tags are only checked when padding needs to be added + // because parts of the code may need to reserialize received messages + // and those messages may, legitimately include padding. + DCHECK(false) << "Message needed padding but already contained a PAD tag"; + return NULL; + } + + if (it->first > kPAD && need_pad_tag) { + need_pad_tag = false; + if (!WritePadTag(&writer, pad_length, &end_offset)) { + return NULL; + } + } + if (!writer.WriteUInt32(it->first)) { DCHECK(false) << "Failed to write tag."; return NULL; @@ -203,14 +228,36 @@ QuicData* CryptoFramer::ConstructHandshakeMessage( } } + if (need_pad_tag) { + if (!WritePadTag(&writer, pad_length, &end_offset)) { + return NULL; + } + } + // Values - for (it = message.tag_value_map().begin(); + for (QuicTagValueMap::const_iterator it = message.tag_value_map().begin(); it != message.tag_value_map().end(); ++it) { + if (it->first > kPAD && need_pad_value) { + need_pad_value = false; + if (!writer.WriteRepeatedByte('-', pad_length)) { + DCHECK(false) << "Failed to write padding."; + return NULL; + } + } + if (!writer.WriteBytes(it->second.data(), it->second.length())) { DCHECK(false) << "Failed to write value."; return NULL; } } + + if (need_pad_value) { + if (!writer.WriteRepeatedByte('-', pad_length)) { + DCHECK(false) << "Failed to write padding."; + return NULL; + } + } + return new QuicData(writer.take(), len, true); } @@ -221,4 +268,20 @@ void CryptoFramer::Clear() { state_ = STATE_READING_TAG; } +// static +bool CryptoFramer::WritePadTag(QuicDataWriter* writer, + size_t pad_length, + uint32* end_offset) { + if (!writer->WriteUInt32(kPAD)) { + DCHECK(false) << "Failed to write tag."; + return false; + } + *end_offset += pad_length; + if (!writer->WriteUInt32(*end_offset)) { + DCHECK(false) << "Failed to write end offset."; + return false; + } + return true; +} + } // namespace net |