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( |
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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 } | 250 } |
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 // 4-7: Verify that the HMAC-SHA1 of all but the first 16 bytes of the |
259 scoped_array<uint8> msg_digest(new uint8[msg_hasher_.DigestLength()]); | 261 // masked message with nonce equals the first 16 bytes of the masked message |
260 msg_hasher_.Sign( | 262 // with nonce. |
| 263 if (!msg_hasher_.VerifyTruncated( |
261 base::StringPiece(read_buf_->data() + kNoncePosition, | 264 base::StringPiece(read_buf_->data() + kNoncePosition, |
262 size - kNoncePosition), | 265 size - kNoncePosition), |
263 msg_digest.get(), msg_hasher_.DigestLength()); | 266 base::StringPiece(read_buf_->data(), kKeySize))) { |
| 267 return net::ERR_INVALID_RESPONSE; |
| 268 } |
264 | 269 |
265 // 6. Compare the hash values. | 270 // 8-11. Decrypt the message. |
266 int ret = memcmp(read_buf_->data(), msg_digest.get(), kKeySize); | |
267 if (ret) | |
268 return net::ERR_INVALID_RESPONSE; | |
269 | |
270 // 7. Decrypt the message. | |
271 std::string nonce = std::string( | 271 std::string nonce = std::string( |
272 read_buf_->data() + kNoncePosition, kKeySize); | 272 read_buf_->data() + kNoncePosition, kKeySize); |
273 CHECK(encryptor_.SetCounter(nonce)); | 273 CHECK(encryptor_.SetCounter(nonce)); |
274 const int raw_message_size = size - kRawMessagePosition; | 274 const int raw_message_size = size - kRawMessagePosition; |
275 | 275 |
276 // TODO(hclam): Change Encryptor API to trim this memcpy. | 276 // TODO(hclam): Change Encryptor API to trim this memcpy. |
277 std::string encrypted_message(read_buf_->data() + kRawMessagePosition, | 277 std::string encrypted_message(read_buf_->data() + kRawMessagePosition, |
278 raw_message_size); | 278 raw_message_size); |
279 std::string raw_message; | 279 std::string raw_message; |
280 CHECK(encryptor_.Decrypt(encrypted_message, &raw_message)); | 280 CHECK(encryptor_.Decrypt(encrypted_message, &raw_message)); |
281 | 281 |
282 if (raw_message_size < kSeqNumberSize) | 282 if (raw_message_size < kSeqNumberSize) |
283 return net::ERR_INVALID_RESPONSE; | 283 return net::ERR_INVALID_RESPONSE; |
284 | 284 |
285 // 12. Read the sequence number. | 285 // 12. Read the sequence number. |
286 uint64 seq_number = GetBE64(raw_message.data()); | 286 uint64 seq_number = GetBE64(raw_message.data()); |
287 | 287 |
288 // The spec says we reject the packet if it is out of order. We don't do | 288 // 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. | 289 // this so allow upper levels to do reordering. |
290 | 290 |
291 // 14. Save the most recent sequence number. | 291 // 14. Save the most recent sequence number. |
292 read_seq_ = seq_number; | 292 read_seq_ = seq_number; |
293 | 293 |
294 // 15. Parse the frame type. | 294 // 15. Parse the frame type. |
295 if (raw_message_size < kSeqNumberSize + kFrameTypeSize) | 295 if (raw_message_size < kSeqNumberSize + kFrameTypeSize) |
296 return net::ERR_INVALID_RESPONSE; | 296 return net::ERR_INVALID_RESPONSE; |
297 ret = memcmp(raw_message.data() + kSeqNumberSize, kFrameType, | 297 if (memcmp(raw_message.data() + kSeqNumberSize, kFrameType, |
298 kFrameTypeSize); | 298 kFrameTypeSize) != 0) { |
299 if (ret) | |
300 return net::ERR_INVALID_RESPONSE; | 299 return net::ERR_INVALID_RESPONSE; |
| 300 } |
301 | 301 |
302 // 16. Read the message. | 302 // 16. Read the message. |
303 const int kMessageSize = raw_message_size - kSeqNumberSize - kFrameTypeSize; | 303 const int kMessageSize = raw_message_size - kSeqNumberSize - kFrameTypeSize; |
304 memcpy(user_read_buf_->data(), | 304 memcpy(user_read_buf_->data(), |
305 raw_message.data() + kSeqNumberSize + kFrameTypeSize, kMessageSize); | 305 raw_message.data() + kSeqNumberSize + kFrameTypeSize, kMessageSize); |
306 return kMessageSize; | 306 return kMessageSize; |
307 } | 307 } |
308 | 308 |
309 } // namespace protocol | 309 } // namespace protocol |
310 } // namespace remoting | 310 } // namespace remoting |
OLD | NEW |