| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/crypto/crypto_framer.h" | 5 #include "net/quic/crypto/crypto_framer.h" |
| 6 | 6 |
| 7 #include "net/quic/crypto/crypto_handshake.h" | 7 #include "net/quic/crypto/crypto_handshake.h" |
| 8 #include "net/quic/quic_data_reader.h" | 8 #include "net/quic/quic_data_reader.h" |
| 9 #include "net/quic/quic_data_writer.h" | 9 #include "net/quic/quic_data_writer.h" |
| 10 | 10 |
| 11 using base::StringPiece; | 11 using base::StringPiece; |
| 12 using std::make_pair; |
| 13 using std::pair; |
| 14 using std::vector; |
| 12 | 15 |
| 13 namespace net { | 16 namespace net { |
| 14 | 17 |
| 15 namespace { | 18 namespace { |
| 16 | 19 |
| 17 const size_t kCryptoTagSize = sizeof(uint32); | 20 const size_t kCryptoTagSize = sizeof(uint32); |
| 21 const size_t kCryptoEndOffsetSize = sizeof(uint32); |
| 18 const size_t kNumEntriesSize = sizeof(uint16); | 22 const size_t kNumEntriesSize = sizeof(uint16); |
| 19 const size_t kValueLenSize = sizeof(uint16); | 23 const size_t kValueLenSize = sizeof(uint16); |
| 20 | 24 |
| 21 // OneShotVisitor is a framer visitor that records a single handshake message. | 25 // OneShotVisitor is a framer visitor that records a single handshake message. |
| 22 class OneShotVisitor : public CryptoFramerVisitorInterface { | 26 class OneShotVisitor : public CryptoFramerVisitorInterface { |
| 23 public: | 27 public: |
| 24 explicit OneShotVisitor(CryptoHandshakeMessage* out) | 28 explicit OneShotVisitor(CryptoHandshakeMessage* out) |
| 25 : out_(out), | 29 : out_(out), |
| 26 error_(false) { | 30 error_(false) { |
| 27 } | 31 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 switch (state_) { | 87 switch (state_) { |
| 84 case STATE_READING_TAG: | 88 case STATE_READING_TAG: |
| 85 if (reader.BytesRemaining() < kCryptoTagSize) { | 89 if (reader.BytesRemaining() < kCryptoTagSize) { |
| 86 break; | 90 break; |
| 87 } | 91 } |
| 88 CryptoTag message_tag; | 92 CryptoTag message_tag; |
| 89 reader.ReadUInt32(&message_tag); | 93 reader.ReadUInt32(&message_tag); |
| 90 message_.set_tag(message_tag); | 94 message_.set_tag(message_tag); |
| 91 state_ = STATE_READING_NUM_ENTRIES; | 95 state_ = STATE_READING_NUM_ENTRIES; |
| 92 case STATE_READING_NUM_ENTRIES: | 96 case STATE_READING_NUM_ENTRIES: |
| 93 if (reader.BytesRemaining() < kNumEntriesSize) { | 97 if (reader.BytesRemaining() < kNumEntriesSize + sizeof(uint16)) { |
| 94 break; | 98 break; |
| 95 } | 99 } |
| 96 reader.ReadUInt16(&num_entries_); | 100 reader.ReadUInt16(&num_entries_); |
| 97 if (num_entries_ > kMaxEntries) { | 101 if (num_entries_ > kMaxEntries) { |
| 98 error_ = QUIC_CRYPTO_TOO_MANY_ENTRIES; | 102 error_ = QUIC_CRYPTO_TOO_MANY_ENTRIES; |
| 99 return false; | 103 return false; |
| 100 } | 104 } |
| 101 state_ = STATE_READING_KEY_TAGS; | 105 uint16 padding; |
| 102 case STATE_READING_KEY_TAGS: | 106 reader.ReadUInt16(&padding); |
| 103 if (reader.BytesRemaining() < num_entries_ * kCryptoTagSize) { | 107 |
| 108 tags_and_lengths_.reserve(num_entries_); |
| 109 state_ = STATE_READING_TAGS_AND_LENGTHS; |
| 110 values_len_ = 0; |
| 111 case STATE_READING_TAGS_AND_LENGTHS: { |
| 112 if (reader.BytesRemaining() < num_entries_ * (kCryptoTagSize + |
| 113 kCryptoEndOffsetSize)) { |
| 104 break; | 114 break; |
| 105 } | 115 } |
| 106 for (int i = 0; i < num_entries_; ++i) { | 116 |
| 117 uint32 last_end_offset = 0; |
| 118 for (unsigned i = 0; i < num_entries_; ++i) { |
| 107 CryptoTag tag; | 119 CryptoTag tag; |
| 108 reader.ReadUInt32(&tag); | 120 reader.ReadUInt32(&tag); |
| 109 if (i > 0 && tag <= tags_.back()) { | 121 if (i > 0 && tag <= tags_and_lengths_[i-1].first) { |
| 122 if (tag == tags_and_lengths_[i-1].first) { |
| 123 error_ = QUIC_CRYPTO_DUPLICATE_TAG; |
| 124 } else { |
| 125 error_ = QUIC_CRYPTO_TAGS_OUT_OF_ORDER; |
| 126 } |
| 127 return false; |
| 128 } |
| 129 |
| 130 uint32 end_offset; |
| 131 reader.ReadUInt32(&end_offset); |
| 132 |
| 133 if (end_offset < last_end_offset) { |
| 110 error_ = QUIC_CRYPTO_TAGS_OUT_OF_ORDER; | 134 error_ = QUIC_CRYPTO_TAGS_OUT_OF_ORDER; |
| 111 return false; | 135 return false; |
| 112 } | 136 } |
| 113 tags_.push_back(tag); | 137 tags_and_lengths_.push_back( |
| 138 make_pair(tag, static_cast<size_t>(end_offset - last_end_offset))); |
| 139 last_end_offset = end_offset; |
| 114 } | 140 } |
| 115 state_ = STATE_READING_LENGTHS; | 141 values_len_ = last_end_offset; |
| 116 case STATE_READING_LENGTHS: { | |
| 117 size_t expected_bytes = num_entries_ * kValueLenSize; | |
| 118 bool has_padding = (num_entries_ % 2 == 1); | |
| 119 if (has_padding) { | |
| 120 expected_bytes += kValueLenSize; | |
| 121 } | |
| 122 if (reader.BytesRemaining() < expected_bytes) { | |
| 123 break; | |
| 124 } | |
| 125 values_len_ = 0; | |
| 126 for (int i = 0; i < num_entries_; ++i) { | |
| 127 uint16 len; | |
| 128 reader.ReadUInt16(&len); | |
| 129 tag_length_map_[tags_[i]] = len; | |
| 130 values_len_ += len; | |
| 131 } | |
| 132 // Possible padding | |
| 133 if (has_padding) { | |
| 134 uint16 len; | |
| 135 reader.ReadUInt16(&len); | |
| 136 if (len != 0) { | |
| 137 error_ = QUIC_CRYPTO_INVALID_VALUE_LENGTH; | |
| 138 return false; | |
| 139 } | |
| 140 } | |
| 141 state_ = STATE_READING_VALUES; | 142 state_ = STATE_READING_VALUES; |
| 142 } | 143 } |
| 143 case STATE_READING_VALUES: | 144 case STATE_READING_VALUES: |
| 144 if (reader.BytesRemaining() < values_len_) { | 145 if (reader.BytesRemaining() < values_len_) { |
| 145 break; | 146 break; |
| 146 } | 147 } |
| 147 for (int i = 0; i < num_entries_; ++i) { | 148 for (vector<pair<CryptoTag, size_t> >::const_iterator |
| 149 it = tags_and_lengths_.begin(); it != tags_and_lengths_.end(); |
| 150 it++) { |
| 148 StringPiece value; | 151 StringPiece value; |
| 149 reader.ReadStringPiece(&value, tag_length_map_[tags_[i]]); | 152 reader.ReadStringPiece(&value, it->second); |
| 150 message_.SetStringPiece(tags_[i], value); | 153 message_.SetStringPiece(it->first, value); |
| 151 } | 154 } |
| 152 visitor_->OnHandshakeMessage(message_); | 155 visitor_->OnHandshakeMessage(message_); |
| 153 Clear(); | 156 Clear(); |
| 154 state_ = STATE_READING_TAG; | 157 state_ = STATE_READING_TAG; |
| 155 break; | 158 break; |
| 156 } | 159 } |
| 157 // Save any remaining data. | 160 // Save any remaining data. |
| 158 buffer_ = reader.PeekRemainingPayload().as_string(); | 161 buffer_ = reader.PeekRemainingPayload().as_string(); |
| 159 return true; | 162 return true; |
| 160 } | 163 } |
| 161 | 164 |
| 162 // static | 165 // static |
| 163 QuicData* CryptoFramer::ConstructHandshakeMessage( | 166 QuicData* CryptoFramer::ConstructHandshakeMessage( |
| 164 const CryptoHandshakeMessage& message) { | 167 const CryptoHandshakeMessage& message) { |
| 165 if (message.tag_value_map().size() > kMaxEntries) { | 168 if (message.tag_value_map().size() > kMaxEntries) { |
| 166 return NULL; | 169 return NULL; |
| 167 } | 170 } |
| 168 size_t len = sizeof(uint32); // message tag | 171 size_t len = kCryptoTagSize; // message tag |
| 169 len += sizeof(uint16); // number of map entries | 172 len += sizeof(uint16); // number of map entries |
| 173 len += sizeof(uint16); // padding. |
| 170 CryptoTagValueMap::const_iterator it = message.tag_value_map().begin(); | 174 CryptoTagValueMap::const_iterator it = message.tag_value_map().begin(); |
| 171 while (it != message.tag_value_map().end()) { | 175 while (it != message.tag_value_map().end()) { |
| 172 len += sizeof(uint32); // tag | 176 len += kCryptoTagSize; // tag |
| 173 len += sizeof(uint16); // value len | 177 len += kCryptoEndOffsetSize; // end offset |
| 174 len += it->second.length(); // value | 178 len += it->second.length(); // value |
| 175 ++it; | 179 ++it; |
| 176 } | 180 } |
| 177 if (message.tag_value_map().size() % 2 == 1) { | |
| 178 len += sizeof(uint16); // padding | |
| 179 } | |
| 180 | 181 |
| 181 QuicDataWriter writer(len); | 182 QuicDataWriter writer(len); |
| 182 if (!writer.WriteUInt32(message.tag())) { | 183 if (!writer.WriteUInt32(message.tag())) { |
| 183 DCHECK(false) << "Failed to write message tag."; | 184 DCHECK(false) << "Failed to write message tag."; |
| 184 return NULL; | 185 return NULL; |
| 185 } | 186 } |
| 186 if (!writer.WriteUInt16(message.tag_value_map().size())) { | 187 if (!writer.WriteUInt16(message.tag_value_map().size())) { |
| 187 DCHECK(false) << "Failed to write size."; | 188 DCHECK(false) << "Failed to write size."; |
| 188 return NULL; | 189 return NULL; |
| 189 } | 190 } |
| 190 // Tags | 191 if (!writer.WriteUInt16(0)) { |
| 192 DCHECK(false) << "Failed to write padding."; |
| 193 return NULL; |
| 194 } |
| 195 |
| 196 uint32 end_offset = 0; |
| 197 // Tags and offsets |
| 191 for (it = message.tag_value_map().begin(); | 198 for (it = message.tag_value_map().begin(); |
| 192 it != message.tag_value_map().end(); ++it) { | 199 it != message.tag_value_map().end(); ++it) { |
| 193 if (!writer.WriteUInt32(it->first)) { | 200 if (!writer.WriteUInt32(it->first)) { |
| 194 DCHECK(false) << "Failed to write tag."; | 201 DCHECK(false) << "Failed to write tag."; |
| 195 return NULL; | 202 return NULL; |
| 196 } | 203 } |
| 197 } | 204 end_offset += it->second.length(); |
| 198 // Lengths | 205 if (!writer.WriteUInt32(end_offset)) { |
| 199 for (it = message.tag_value_map().begin(); | 206 DCHECK(false) << "Failed to write end offset."; |
| 200 it != message.tag_value_map().end(); ++it) { | |
| 201 if (!writer.WriteUInt16(it->second.length())) { | |
| 202 DCHECK(false) << "Failed to write length."; | |
| 203 return NULL; | 207 return NULL; |
| 204 } | 208 } |
| 205 } | 209 } |
| 206 // Possible padding | 210 |
| 207 if (message.tag_value_map().size() % 2 == 1) { | |
| 208 if (!writer.WriteUInt16(0)) { | |
| 209 DCHECK(false) << "Failed to write padding."; | |
| 210 return NULL; | |
| 211 } | |
| 212 } | |
| 213 // Values | 211 // Values |
| 214 for (it = message.tag_value_map().begin(); | 212 for (it = message.tag_value_map().begin(); |
| 215 it != message.tag_value_map().end(); ++it) { | 213 it != message.tag_value_map().end(); ++it) { |
| 216 if (!writer.WriteBytes(it->second.data(), it->second.length())) { | 214 if (!writer.WriteBytes(it->second.data(), it->second.length())) { |
| 217 DCHECK(false) << "Failed to write value."; | 215 DCHECK(false) << "Failed to write value."; |
| 218 return NULL; | 216 return NULL; |
| 219 } | 217 } |
| 220 } | 218 } |
| 221 return new QuicData(writer.take(), len, true); | 219 return new QuicData(writer.take(), len, true); |
| 222 } | 220 } |
| 223 | 221 |
| 224 void CryptoFramer::Clear() { | 222 void CryptoFramer::Clear() { |
| 225 message_.Clear(); | 223 message_.Clear(); |
| 226 tag_length_map_.clear(); | 224 tags_and_lengths_.clear(); |
| 227 tags_.clear(); | |
| 228 error_ = QUIC_NO_ERROR; | 225 error_ = QUIC_NO_ERROR; |
| 229 state_ = STATE_READING_TAG; | 226 state_ = STATE_READING_TAG; |
| 230 } | 227 } |
| 231 | 228 |
| 232 } // namespace net | 229 } // namespace net |
| OLD | NEW |