Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: net/quic/crypto/crypto_framer.cc

Issue 14718011: Land Recent QUIC Changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/quic/crypto/crypto_framer.h ('k') | net/quic/crypto/crypto_framer_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
OLDNEW
« no previous file with comments | « net/quic/crypto/crypto_framer.h ('k') | net/quic/crypto/crypto_framer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698