OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "remoting/protocol/secure_p2p_socket.h" | 5 #include "remoting/protocol/secure_p2p_socket.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/rand_util.h" | 8 #include "base/rand_util.h" |
9 #include "crypto/symmetric_key.h" | 9 #include "crypto/symmetric_key.h" |
10 #include "net/base/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 msg_hasher_(crypto::HMAC::SHA1) { | 84 msg_hasher_(crypto::HMAC::SHA1) { |
85 // Make sure the key is valid. | 85 // Make sure the key is valid. |
86 CHECK(ice_key.size() == kKeySize); | 86 CHECK(ice_key.size() == kKeySize); |
87 | 87 |
88 // Create the mask key from ice key. | 88 // Create the mask key from ice key. |
89 crypto::HMAC mask_hasher(crypto::HMAC::SHA1); | 89 crypto::HMAC mask_hasher(crypto::HMAC::SHA1); |
90 bool ret = mask_hasher.Init( | 90 bool ret = mask_hasher.Init( |
91 reinterpret_cast<const unsigned char*>(ice_key.data()), kKeySize); | 91 reinterpret_cast<const unsigned char*>(ice_key.data()), kKeySize); |
92 DCHECK(ret) << "Initialize HMAC-SHA1 for mask failed."; | 92 DCHECK(ret) << "Initialize HMAC-SHA1 for mask failed."; |
93 scoped_array<uint8> mask_digest(new uint8[mask_hasher.DigestLength()]); | 93 scoped_array<uint8> mask_digest(new uint8[mask_hasher.DigestLength()]); |
94 mask_hasher.Sign(kMaskSaltStr, mask_digest.get(), | 94 ret = mask_hasher.Sign(kMaskSaltStr, mask_digest.get(), |
95 mask_hasher.DigestLength()); | 95 mask_hasher.DigestLength()); |
96 DCHECK(ret) << "Sign with HMAC-SHA1 for mask failed."; | |
96 mask_key_.reset(crypto::SymmetricKey::Import( | 97 mask_key_.reset(crypto::SymmetricKey::Import( |
97 crypto::SymmetricKey::AES, | 98 crypto::SymmetricKey::AES, |
98 std::string(mask_digest.get(), mask_digest.get() + kKeySize))); | 99 std::string(mask_digest.get(), mask_digest.get() + kKeySize))); |
99 DCHECK(mask_key_.get()) << "Import symmetric key failed."; | 100 DCHECK(mask_key_.get()) << "Import symmetric key failed."; |
100 | 101 |
101 // Initialize the encryptor with mask key. | 102 // Initialize the encryptor with mask key. |
102 encryptor_.Init(mask_key_.get(), crypto::Encryptor::CTR, ""); | 103 encryptor_.Init(mask_key_.get(), crypto::Encryptor::CTR, ""); |
103 | 104 |
104 // Create the hash key from ice key. | 105 // Create the hash key from ice key. |
105 crypto::HMAC hash_hasher(crypto::HMAC::SHA1); | 106 crypto::HMAC hash_hasher(crypto::HMAC::SHA1); |
106 ret = hash_hasher.Init( | 107 ret = hash_hasher.Init( |
107 reinterpret_cast<const unsigned char*>(ice_key.data()), kKeySize); | 108 reinterpret_cast<const unsigned char*>(ice_key.data()), kKeySize); |
108 DCHECK(ret) << "Initialize HMAC-SHA1 for hash failed."; | 109 DCHECK(ret) << "Initialize HMAC-SHA1 for hash failed."; |
109 scoped_array<uint8> hash_key(new uint8[hash_hasher.DigestLength()]); | 110 scoped_array<uint8> hash_key(new uint8[hash_hasher.DigestLength()]); |
110 hash_hasher.Sign(kHashSaltStr, hash_key.get(), hash_hasher.DigestLength()); | 111 ret = hash_hasher.Sign(kHashSaltStr, hash_key.get(), |
111 | 112 hash_hasher.DigestLength()); |
113 DCHECK(ret) << "Sign with HMAC-SHA1 for hash failed."; | |
112 // Create a hasher for message. | 114 // Create a hasher for message. |
113 ret = msg_hasher_.Init(hash_key.get(), kKeySize); | 115 ret = msg_hasher_.Init(hash_key.get(), kKeySize); |
114 DCHECK(ret) << "Initialize HMAC-SHA1 for message failed."; | 116 DCHECK(ret) << "Initialize HMAC-SHA1 for message failed."; |
115 } | 117 } |
116 | 118 |
117 SecureP2PSocket::~SecureP2PSocket() { | 119 SecureP2PSocket::~SecureP2PSocket() { |
118 } | 120 } |
119 | 121 |
120 int SecureP2PSocket::Read(IOBuffer* buf, int buf_len, | 122 int SecureP2PSocket::Read(IOBuffer* buf, int buf_len, |
121 CompletionCallback* callback) { | 123 CompletionCallback* callback) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
157 std::string encrypted_message; | 159 std::string encrypted_message; |
158 CHECK(encryptor_.Encrypt(raw_message, &encrypted_message)); | 160 CHECK(encryptor_.Encrypt(raw_message, &encrypted_message)); |
159 memcpy(encrypted_buf->data() + kRawMessagePosition, | 161 memcpy(encrypted_buf->data() + kRawMessagePosition, |
160 encrypted_message.data(), encrypted_message.size()); | 162 encrypted_message.data(), encrypted_message.size()); |
161 | 163 |
162 // 8. Concatenate nonce and encrypted message to form masked message. | 164 // 8. Concatenate nonce and encrypted message to form masked message. |
163 memcpy(encrypted_buf->data() + kNoncePosition, nonce.data(), kKeySize); | 165 memcpy(encrypted_buf->data() + kNoncePosition, nonce.data(), kKeySize); |
164 | 166 |
165 // 10. Create hash from masked message with nonce. | 167 // 10. Create hash from masked message with nonce. |
166 scoped_array<uint8> msg_digest(new uint8[msg_hasher_.DigestLength()]); | 168 scoped_array<uint8> msg_digest(new uint8[msg_hasher_.DigestLength()]); |
167 msg_hasher_.Sign( | 169 CHECK(msg_hasher_.Sign( |
Denis Lagno
2011/07/28 08:13:37
nit: I understand that CHECK is executed always, b
| |
168 base::StringPiece(encrypted_buf->data() + kNoncePosition, | 170 base::StringPiece(encrypted_buf->data() + kNoncePosition, |
169 kRawMessageSize + kKeySize), | 171 kRawMessageSize + kKeySize), |
170 msg_digest.get(), msg_hasher_.DigestLength()); | 172 msg_digest.get(), msg_hasher_.DigestLength())); |
171 memcpy(encrypted_buf->data() + kHashPosition, msg_digest.get(), kKeySize); | 173 memcpy(encrypted_buf->data() + kHashPosition, msg_digest.get(), kKeySize); |
172 | 174 |
173 // Write to the socket. | 175 // Write to the socket. |
174 int ret = socket_->Write(encrypted_buf, encrypted_buffer_size, | 176 int ret = socket_->Write(encrypted_buf, encrypted_buffer_size, |
175 write_callback_.get()); | 177 write_callback_.get()); |
176 if (ret == net::ERR_IO_PENDING) { | 178 if (ret == net::ERR_IO_PENDING) { |
177 DCHECK(callback); | 179 DCHECK(callback); |
178 user_write_callback_ = callback; | 180 user_write_callback_ = callback; |
179 user_write_buf_len_ = buf_len; | 181 user_write_buf_len_ = buf_len; |
180 return ret; | 182 return ret; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 callback->Run(err); | 251 callback->Run(err); |
250 } | 252 } |
251 | 253 |
252 int SecureP2PSocket::DecryptBuffer(int size) { | 254 int SecureP2PSocket::DecryptBuffer(int size) { |
253 if (size < kRawMessagePosition) | 255 if (size < kRawMessagePosition) |
254 return net::ERR_INVALID_RESPONSE; | 256 return net::ERR_INVALID_RESPONSE; |
255 | 257 |
256 // See the spec for the steps taken in this method: | 258 // See the spec for the steps taken in this method: |
257 // http://www.whatwg.org/specs/web-apps/current-work/complete/video-conferenci ng-and-peer-to-peer-communication.html#peer-to-peer-connections | 259 // http://www.whatwg.org/specs/web-apps/current-work/complete/video-conferenci ng-and-peer-to-peer-communication.html#peer-to-peer-connections |
258 // 5. Compute hash of the message. | 260 // 5. Compute hash of the message. |
259 scoped_array<uint8> msg_digest(new uint8[msg_hasher_.DigestLength()]); | 261 // 6. Compare the hash values. |
260 msg_hasher_.Sign( | 262 if (!msg_hasher_.Verify( |
261 base::StringPiece(read_buf_->data() + kNoncePosition, | 263 base::StringPiece(read_buf_->data() + kNoncePosition, |
262 size - kNoncePosition), | 264 size - kNoncePosition), |
263 msg_digest.get(), msg_hasher_.DigestLength()); | 265 base::StringPiece(read_buf_->data(), kKeySize))) { |
264 | |
265 // 6. Compare the hash values. | |
266 int ret = memcmp(read_buf_->data(), msg_digest.get(), kKeySize); | |
267 if (ret) | |
268 return net::ERR_INVALID_RESPONSE; | 266 return net::ERR_INVALID_RESPONSE; |
267 } | |
269 | 268 |
270 // 7. Decrypt the message. | 269 // 7. Decrypt the message. |
271 std::string nonce = std::string( | 270 std::string nonce = std::string( |
272 read_buf_->data() + kNoncePosition, kKeySize); | 271 read_buf_->data() + kNoncePosition, kKeySize); |
273 CHECK(encryptor_.SetCounter(nonce)); | 272 CHECK(encryptor_.SetCounter(nonce)); |
274 const int raw_message_size = size - kRawMessagePosition; | 273 const int raw_message_size = size - kRawMessagePosition; |
275 | 274 |
276 // TODO(hclam): Change Encryptor API to trim this memcpy. | 275 // TODO(hclam): Change Encryptor API to trim this memcpy. |
277 std::string encrypted_message(read_buf_->data() + kRawMessagePosition, | 276 std::string encrypted_message(read_buf_->data() + kRawMessagePosition, |
278 raw_message_size); | 277 raw_message_size); |
279 std::string raw_message; | 278 std::string raw_message; |
280 CHECK(encryptor_.Decrypt(encrypted_message, &raw_message)); | 279 CHECK(encryptor_.Decrypt(encrypted_message, &raw_message)); |
281 | 280 |
282 if (raw_message_size < kSeqNumberSize) | 281 if (raw_message_size < kSeqNumberSize) |
283 return net::ERR_INVALID_RESPONSE; | 282 return net::ERR_INVALID_RESPONSE; |
284 | 283 |
285 // 12. Read the sequence number. | 284 // 12. Read the sequence number. |
286 uint64 seq_number = GetBE64(raw_message.data()); | 285 uint64 seq_number = GetBE64(raw_message.data()); |
287 | 286 |
288 // The spec says we reject the packet if it is out of order. We don't do | 287 // The spec says we reject the packet if it is out of order. We don't do |
289 // this so allow upper levels to do reordering. | 288 // this so allow upper levels to do reordering. |
290 | 289 |
291 // 14. Save the most recent sequence number. | 290 // 14. Save the most recent sequence number. |
292 read_seq_ = seq_number; | 291 read_seq_ = seq_number; |
293 | 292 |
294 // 15. Parse the frame type. | 293 // 15. Parse the frame type. |
295 if (raw_message_size < kSeqNumberSize + kFrameTypeSize) | 294 if (raw_message_size < kSeqNumberSize + kFrameTypeSize) |
296 return net::ERR_INVALID_RESPONSE; | 295 return net::ERR_INVALID_RESPONSE; |
297 ret = memcmp(raw_message.data() + kSeqNumberSize, kFrameType, | 296 if (memcmp(raw_message.data() + kSeqNumberSize, kFrameType, |
298 kFrameTypeSize); | 297 kFrameTypeSize) != 0) { |
299 if (ret) | |
300 return net::ERR_INVALID_RESPONSE; | 298 return net::ERR_INVALID_RESPONSE; |
299 } | |
301 | 300 |
302 // 16. Read the message. | 301 // 16. Read the message. |
303 const int kMessageSize = raw_message_size - kSeqNumberSize - kFrameTypeSize; | 302 const int kMessageSize = raw_message_size - kSeqNumberSize - kFrameTypeSize; |
304 memcpy(user_read_buf_->data(), | 303 memcpy(user_read_buf_->data(), |
305 raw_message.data() + kSeqNumberSize + kFrameTypeSize, kMessageSize); | 304 raw_message.data() + kSeqNumberSize + kFrameTypeSize, kMessageSize); |
306 return kMessageSize; | 305 return kMessageSize; |
307 } | 306 } |
308 | 307 |
309 } // namespace protocol | 308 } // namespace protocol |
310 } // namespace remoting | 309 } // namespace remoting |
OLD | NEW |