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; | 12 using std::make_pair; |
13 using std::pair; | 13 using std::pair; |
14 using std::vector; | 14 using std::vector; |
15 | 15 |
16 namespace net { | 16 namespace net { |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 const size_t kCryptoTagSize = sizeof(uint32); | 20 const size_t kQuicTagSize = sizeof(uint32); |
21 const size_t kCryptoEndOffsetSize = sizeof(uint32); | 21 const size_t kCryptoEndOffsetSize = sizeof(uint32); |
22 const size_t kNumEntriesSize = sizeof(uint16); | 22 const size_t kNumEntriesSize = sizeof(uint16); |
23 const size_t kValueLenSize = sizeof(uint16); | 23 const size_t kValueLenSize = sizeof(uint16); |
24 | 24 |
25 // OneShotVisitor is a framer visitor that records a single handshake message. | 25 // OneShotVisitor is a framer visitor that records a single handshake message. |
26 class OneShotVisitor : public CryptoFramerVisitorInterface { | 26 class OneShotVisitor : public CryptoFramerVisitorInterface { |
27 public: | 27 public: |
28 explicit OneShotVisitor(CryptoHandshakeMessage* out) | 28 explicit OneShotVisitor(CryptoHandshakeMessage* out) |
29 : out_(out), | 29 : out_(out), |
30 error_(false) { | 30 error_(false) { |
31 } | 31 } |
32 | 32 |
33 virtual void OnError(CryptoFramer* framer) OVERRIDE { | 33 virtual void OnError(CryptoFramer* framer) OVERRIDE { error_ = true; } |
34 error_ = true; | |
35 } | |
36 | 34 |
37 virtual void OnHandshakeMessage( | 35 virtual void OnHandshakeMessage( |
38 const CryptoHandshakeMessage& message) OVERRIDE { | 36 const CryptoHandshakeMessage& message) OVERRIDE { |
39 *out_ = message; | 37 *out_ = message; |
40 } | 38 } |
41 | 39 |
42 bool error() const { | 40 bool error() const { return error_; } |
43 return error_; | |
44 } | |
45 | 41 |
46 private: | 42 private: |
47 CryptoHandshakeMessage* const out_; | 43 CryptoHandshakeMessage* const out_; |
48 bool error_; | 44 bool error_; |
49 }; | 45 }; |
50 | 46 |
51 } // namespace | 47 } // namespace |
52 | 48 |
53 CryptoFramer::CryptoFramer() | 49 CryptoFramer::CryptoFramer() |
54 : visitor_(NULL), | 50 : visitor_(NULL), |
55 num_entries_(0), | 51 num_entries_(0), |
56 values_len_(0) { | 52 values_len_(0) { |
57 Clear(); | 53 Clear(); |
58 } | 54 } |
59 | 55 |
60 CryptoFramer::~CryptoFramer() {} | 56 CryptoFramer::~CryptoFramer() {} |
61 | 57 |
62 // static | 58 // static |
63 CryptoHandshakeMessage* CryptoFramer::ParseMessage(StringPiece in) { | 59 CryptoHandshakeMessage* CryptoFramer::ParseMessage(StringPiece in) { |
64 scoped_ptr<CryptoHandshakeMessage> msg(new CryptoHandshakeMessage); | 60 scoped_ptr<CryptoHandshakeMessage> msg(new CryptoHandshakeMessage); |
65 OneShotVisitor visitor(msg.get()); | 61 OneShotVisitor visitor(msg.get()); |
66 CryptoFramer framer; | 62 CryptoFramer framer; |
67 | 63 |
68 framer.set_visitor(&visitor); | 64 framer.set_visitor(&visitor); |
69 if (!framer.ProcessInput(in) || | 65 if (!framer.ProcessInput(in) || visitor.error() || |
70 visitor.error() || | |
71 framer.InputBytesRemaining()) { | 66 framer.InputBytesRemaining()) { |
72 return NULL; | 67 return NULL; |
73 } | 68 } |
74 | 69 |
75 return msg.release(); | 70 return msg.release(); |
76 } | 71 } |
77 | 72 |
78 bool CryptoFramer::ProcessInput(StringPiece input) { | 73 bool CryptoFramer::ProcessInput(StringPiece input) { |
79 DCHECK_EQ(QUIC_NO_ERROR, error_); | 74 DCHECK_EQ(QUIC_NO_ERROR, error_); |
80 if (error_ != QUIC_NO_ERROR) { | 75 if (error_ != QUIC_NO_ERROR) { |
81 return false; | 76 return false; |
82 } | 77 } |
83 // Add this data to the buffer. | 78 // Add this data to the buffer. |
84 buffer_.append(input.data(), input.length()); | 79 buffer_.append(input.data(), input.length()); |
85 QuicDataReader reader(buffer_.data(), buffer_.length()); | 80 QuicDataReader reader(buffer_.data(), buffer_.length()); |
86 | 81 |
87 switch (state_) { | 82 switch (state_) { |
88 case STATE_READING_TAG: | 83 case STATE_READING_TAG: |
89 if (reader.BytesRemaining() < kCryptoTagSize) { | 84 if (reader.BytesRemaining() < kQuicTagSize) { |
90 break; | 85 break; |
91 } | 86 } |
92 CryptoTag message_tag; | 87 QuicTag message_tag; |
93 reader.ReadUInt32(&message_tag); | 88 reader.ReadUInt32(&message_tag); |
94 message_.set_tag(message_tag); | 89 message_.set_tag(message_tag); |
95 state_ = STATE_READING_NUM_ENTRIES; | 90 state_ = STATE_READING_NUM_ENTRIES; |
96 case STATE_READING_NUM_ENTRIES: | 91 case STATE_READING_NUM_ENTRIES: |
97 if (reader.BytesRemaining() < kNumEntriesSize + sizeof(uint16)) { | 92 if (reader.BytesRemaining() < kNumEntriesSize + sizeof(uint16)) { |
98 break; | 93 break; |
99 } | 94 } |
100 reader.ReadUInt16(&num_entries_); | 95 reader.ReadUInt16(&num_entries_); |
101 if (num_entries_ > kMaxEntries) { | 96 if (num_entries_ > kMaxEntries) { |
102 error_ = QUIC_CRYPTO_TOO_MANY_ENTRIES; | 97 error_ = QUIC_CRYPTO_TOO_MANY_ENTRIES; |
103 return false; | 98 return false; |
104 } | 99 } |
105 uint16 padding; | 100 uint16 padding; |
106 reader.ReadUInt16(&padding); | 101 reader.ReadUInt16(&padding); |
107 | 102 |
108 tags_and_lengths_.reserve(num_entries_); | 103 tags_and_lengths_.reserve(num_entries_); |
109 state_ = STATE_READING_TAGS_AND_LENGTHS; | 104 state_ = STATE_READING_TAGS_AND_LENGTHS; |
110 values_len_ = 0; | 105 values_len_ = 0; |
111 case STATE_READING_TAGS_AND_LENGTHS: { | 106 case STATE_READING_TAGS_AND_LENGTHS: { |
112 if (reader.BytesRemaining() < num_entries_ * (kCryptoTagSize + | 107 if (reader.BytesRemaining() < |
113 kCryptoEndOffsetSize)) { | 108 num_entries_ * (kQuicTagSize + kCryptoEndOffsetSize)) { |
114 break; | 109 break; |
115 } | 110 } |
116 | 111 |
117 uint32 last_end_offset = 0; | 112 uint32 last_end_offset = 0; |
118 for (unsigned i = 0; i < num_entries_; ++i) { | 113 for (unsigned i = 0; i < num_entries_; ++i) { |
119 CryptoTag tag; | 114 QuicTag tag; |
120 reader.ReadUInt32(&tag); | 115 reader.ReadUInt32(&tag); |
121 if (i > 0 && tag <= tags_and_lengths_[i-1].first) { | 116 if (i > 0 && tag <= tags_and_lengths_[i-1].first) { |
122 if (tag == tags_and_lengths_[i-1].first) { | 117 if (tag == tags_and_lengths_[i-1].first) { |
123 error_ = QUIC_CRYPTO_DUPLICATE_TAG; | 118 error_ = QUIC_CRYPTO_DUPLICATE_TAG; |
124 } else { | 119 } else { |
125 error_ = QUIC_CRYPTO_TAGS_OUT_OF_ORDER; | 120 error_ = QUIC_CRYPTO_TAGS_OUT_OF_ORDER; |
126 } | 121 } |
127 return false; | 122 return false; |
128 } | 123 } |
129 | 124 |
130 uint32 end_offset; | 125 uint32 end_offset; |
131 reader.ReadUInt32(&end_offset); | 126 reader.ReadUInt32(&end_offset); |
132 | 127 |
133 if (end_offset < last_end_offset) { | 128 if (end_offset < last_end_offset) { |
134 error_ = QUIC_CRYPTO_TAGS_OUT_OF_ORDER; | 129 error_ = QUIC_CRYPTO_TAGS_OUT_OF_ORDER; |
135 return false; | 130 return false; |
136 } | 131 } |
137 tags_and_lengths_.push_back( | 132 tags_and_lengths_.push_back( |
138 make_pair(tag, static_cast<size_t>(end_offset - last_end_offset))); | 133 make_pair(tag, static_cast<size_t>(end_offset - last_end_offset))); |
139 last_end_offset = end_offset; | 134 last_end_offset = end_offset; |
140 } | 135 } |
141 values_len_ = last_end_offset; | 136 values_len_ = last_end_offset; |
142 state_ = STATE_READING_VALUES; | 137 state_ = STATE_READING_VALUES; |
143 } | 138 } |
144 case STATE_READING_VALUES: | 139 case STATE_READING_VALUES: |
145 if (reader.BytesRemaining() < values_len_) { | 140 if (reader.BytesRemaining() < values_len_) { |
146 break; | 141 break; |
147 } | 142 } |
148 for (vector<pair<CryptoTag, size_t> >::const_iterator | 143 for (vector<pair<QuicTag, size_t> >::const_iterator |
149 it = tags_and_lengths_.begin(); it != tags_and_lengths_.end(); | 144 it = tags_and_lengths_.begin(); it != tags_and_lengths_.end(); |
150 it++) { | 145 it++) { |
151 StringPiece value; | 146 StringPiece value; |
152 reader.ReadStringPiece(&value, it->second); | 147 reader.ReadStringPiece(&value, it->second); |
153 message_.SetStringPiece(it->first, value); | 148 message_.SetStringPiece(it->first, value); |
154 } | 149 } |
155 visitor_->OnHandshakeMessage(message_); | 150 visitor_->OnHandshakeMessage(message_); |
156 Clear(); | 151 Clear(); |
157 state_ = STATE_READING_TAG; | 152 state_ = STATE_READING_TAG; |
158 break; | 153 break; |
159 } | 154 } |
160 // Save any remaining data. | 155 // Save any remaining data. |
161 buffer_ = reader.PeekRemainingPayload().as_string(); | 156 buffer_ = reader.PeekRemainingPayload().as_string(); |
162 return true; | 157 return true; |
163 } | 158 } |
164 | 159 |
165 // static | 160 // static |
166 QuicData* CryptoFramer::ConstructHandshakeMessage( | 161 QuicData* CryptoFramer::ConstructHandshakeMessage( |
167 const CryptoHandshakeMessage& message) { | 162 const CryptoHandshakeMessage& message) { |
168 if (message.tag_value_map().size() > kMaxEntries) { | 163 if (message.tag_value_map().size() > kMaxEntries) { |
169 return NULL; | 164 return NULL; |
170 } | 165 } |
171 size_t len = kCryptoTagSize; // message tag | 166 size_t len = kQuicTagSize; // message tag |
172 len += sizeof(uint16); // number of map entries | 167 len += sizeof(uint16); // number of map entries |
173 len += sizeof(uint16); // padding. | 168 len += sizeof(uint16); // padding. |
174 CryptoTagValueMap::const_iterator it = message.tag_value_map().begin(); | 169 QuicTagValueMap::const_iterator it = message.tag_value_map().begin(); |
175 while (it != message.tag_value_map().end()) { | 170 while (it != message.tag_value_map().end()) { |
176 len += kCryptoTagSize; // tag | 171 len += kQuicTagSize; // tag |
177 len += kCryptoEndOffsetSize; // end offset | 172 len += kCryptoEndOffsetSize; // end offset |
178 len += it->second.length(); // value | 173 len += it->second.length(); // value |
179 ++it; | 174 ++it; |
180 } | 175 } |
181 | 176 |
182 QuicDataWriter writer(len); | 177 QuicDataWriter writer(len); |
183 if (!writer.WriteUInt32(message.tag())) { | 178 if (!writer.WriteUInt32(message.tag())) { |
184 DCHECK(false) << "Failed to write message tag."; | 179 DCHECK(false) << "Failed to write message tag."; |
185 return NULL; | 180 return NULL; |
186 } | 181 } |
187 if (!writer.WriteUInt16(message.tag_value_map().size())) { | 182 if (!writer.WriteUInt16(message.tag_value_map().size())) { |
188 DCHECK(false) << "Failed to write size."; | 183 DCHECK(false) << "Failed to write size."; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 } | 215 } |
221 | 216 |
222 void CryptoFramer::Clear() { | 217 void CryptoFramer::Clear() { |
223 message_.Clear(); | 218 message_.Clear(); |
224 tags_and_lengths_.clear(); | 219 tags_and_lengths_.clear(); |
225 error_ = QUIC_NO_ERROR; | 220 error_ = QUIC_NO_ERROR; |
226 state_ = STATE_READING_TAG; | 221 state_ = STATE_READING_TAG; |
227 } | 222 } |
228 | 223 |
229 } // namespace net | 224 } // namespace net |
OLD | NEW |