| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_utils.h" | 5 #include "net/quic/crypto/crypto_utils.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "crypto/hkdf.h" | 9 #include "crypto/hkdf.h" |
| 10 #include "crypto/secure_hash.h" | 10 #include "crypto/secure_hash.h" |
| 11 #include "net/base/url_util.h" | 11 #include "net/base/url_util.h" |
| 12 #include "net/quic/crypto/crypto_handshake.h" | 12 #include "net/quic/crypto/crypto_handshake.h" |
| 13 #include "net/quic/crypto/crypto_protocol.h" | 13 #include "net/quic/crypto/crypto_protocol.h" |
| 14 #include "net/quic/crypto/quic_decrypter.h" | 14 #include "net/quic/crypto/quic_decrypter.h" |
| 15 #include "net/quic/crypto/quic_encrypter.h" | 15 #include "net/quic/crypto/quic_encrypter.h" |
| 16 #include "net/quic/crypto/quic_random.h" | 16 #include "net/quic/crypto/quic_random.h" |
| 17 #include "net/quic/quic_bug_tracker.h" |
| 17 #include "net/quic/quic_time.h" | 18 #include "net/quic/quic_time.h" |
| 18 #include "net/quic/quic_utils.h" | 19 #include "net/quic/quic_utils.h" |
| 19 #include "url/url_canon.h" | 20 #include "url/url_canon.h" |
| 20 | 21 |
| 21 using base::StringPiece; | 22 using base::StringPiece; |
| 22 using std::numeric_limits; | 23 using std::numeric_limits; |
| 23 using std::string; | 24 using std::string; |
| 24 | 25 |
| 25 namespace net { | 26 namespace net { |
| 26 | 27 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 return host; | 84 return host; |
| 84 } | 85 } |
| 85 | 86 |
| 86 // static | 87 // static |
| 87 bool CryptoUtils::DeriveKeys(StringPiece premaster_secret, | 88 bool CryptoUtils::DeriveKeys(StringPiece premaster_secret, |
| 88 QuicTag aead, | 89 QuicTag aead, |
| 89 StringPiece client_nonce, | 90 StringPiece client_nonce, |
| 90 StringPiece server_nonce, | 91 StringPiece server_nonce, |
| 91 const string& hkdf_input, | 92 const string& hkdf_input, |
| 92 Perspective perspective, | 93 Perspective perspective, |
| 94 Diversification diversification, |
| 93 CrypterPair* crypters, | 95 CrypterPair* crypters, |
| 94 string* subkey_secret) { | 96 string* subkey_secret) { |
| 95 crypters->encrypter.reset(QuicEncrypter::Create(aead)); | 97 crypters->encrypter.reset(QuicEncrypter::Create(aead)); |
| 96 crypters->decrypter.reset(QuicDecrypter::Create(aead)); | 98 crypters->decrypter.reset(QuicDecrypter::Create(aead)); |
| 97 size_t key_bytes = crypters->encrypter->GetKeySize(); | 99 size_t key_bytes = crypters->encrypter->GetKeySize(); |
| 98 size_t nonce_prefix_bytes = crypters->encrypter->GetNoncePrefixSize(); | 100 size_t nonce_prefix_bytes = crypters->encrypter->GetNoncePrefixSize(); |
| 99 size_t subkey_secret_bytes = | 101 size_t subkey_secret_bytes = |
| 100 subkey_secret == nullptr ? 0 : premaster_secret.length(); | 102 subkey_secret == nullptr ? 0 : premaster_secret.length(); |
| 101 | 103 |
| 102 StringPiece nonce = client_nonce; | 104 StringPiece nonce = client_nonce; |
| 103 string nonce_storage; | 105 string nonce_storage; |
| 104 if (!server_nonce.empty()) { | 106 if (!server_nonce.empty()) { |
| 105 nonce_storage = client_nonce.as_string() + server_nonce.as_string(); | 107 nonce_storage = client_nonce.as_string() + server_nonce.as_string(); |
| 106 nonce = nonce_storage; | 108 nonce = nonce_storage; |
| 107 } | 109 } |
| 108 | 110 |
| 109 crypto::HKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes, | 111 crypto::HKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes, |
| 110 nonce_prefix_bytes, subkey_secret_bytes); | 112 nonce_prefix_bytes, subkey_secret_bytes); |
| 111 if (perspective == Perspective::IS_SERVER) { | 113 |
| 112 if (!crypters->encrypter->SetKey(hkdf.server_write_key()) || | 114 // Key derivation depends on the key diversification method being employed. |
| 113 !crypters->encrypter->SetNoncePrefix(hkdf.server_write_iv()) || | 115 // both the client and the server support never doing key diversification. |
| 114 !crypters->decrypter->SetKey(hkdf.client_write_key()) || | 116 // The server also supports immediate diversification, and the client |
| 115 !crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv())) { | 117 // supports pending diversification. |
| 116 return false; | 118 switch (diversification.mode()) { |
| 119 case Diversification::NEVER: { |
| 120 if (perspective == Perspective::IS_SERVER) { |
| 121 if (!crypters->encrypter->SetKey(hkdf.server_write_key()) || |
| 122 !crypters->encrypter->SetNoncePrefix(hkdf.server_write_iv()) || |
| 123 !crypters->decrypter->SetKey(hkdf.client_write_key()) || |
| 124 !crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv())) { |
| 125 return false; |
| 126 } |
| 127 } else { |
| 128 if (!crypters->encrypter->SetKey(hkdf.client_write_key()) || |
| 129 !crypters->encrypter->SetNoncePrefix(hkdf.client_write_iv()) || |
| 130 !crypters->decrypter->SetKey(hkdf.server_write_key()) || |
| 131 !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv())) { |
| 132 return false; |
| 133 } |
| 134 } |
| 135 break; |
| 117 } | 136 } |
| 118 } else { | 137 case Diversification::PENDING: { |
| 119 if (!crypters->encrypter->SetKey(hkdf.client_write_key()) || | 138 if (perspective == Perspective::IS_SERVER) { |
| 120 !crypters->encrypter->SetNoncePrefix(hkdf.client_write_iv()) || | 139 QUIC_BUG << "Pending diversification is only for clients."; |
| 121 !crypters->decrypter->SetKey(hkdf.server_write_key()) || | 140 return false; |
| 122 !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv())) { | 141 } |
| 123 return false; | 142 |
| 143 if (!crypters->encrypter->SetKey(hkdf.client_write_key()) || |
| 144 !crypters->encrypter->SetNoncePrefix(hkdf.client_write_iv()) || |
| 145 !crypters->decrypter->SetPreliminaryKey(hkdf.server_write_key()) || |
| 146 !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv())) { |
| 147 return false; |
| 148 } |
| 149 break; |
| 124 } | 150 } |
| 151 case Diversification::NOW: { |
| 152 if (perspective == Perspective::IS_CLIENT) { |
| 153 QUIC_BUG << "Immediate diversification is only for servers."; |
| 154 return false; |
| 155 } |
| 156 |
| 157 string key, nonce_prefix; |
| 158 QuicDecrypter::DiversifyPreliminaryKey( |
| 159 hkdf.server_write_key(), hkdf.server_write_iv(), |
| 160 *diversification.nonce(), key_bytes, nonce_prefix_bytes, &key, |
| 161 &nonce_prefix); |
| 162 if (!crypters->decrypter->SetKey(hkdf.client_write_key()) || |
| 163 !crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv()) || |
| 164 !crypters->encrypter->SetKey(key) || |
| 165 !crypters->encrypter->SetNoncePrefix(nonce_prefix)) { |
| 166 return false; |
| 167 } |
| 168 break; |
| 169 } |
| 170 default: |
| 171 DCHECK(false); |
| 125 } | 172 } |
| 173 |
| 126 if (subkey_secret != nullptr) { | 174 if (subkey_secret != nullptr) { |
| 127 hkdf.subkey_secret().CopyToString(subkey_secret); | 175 hkdf.subkey_secret().CopyToString(subkey_secret); |
| 128 } | 176 } |
| 129 | 177 |
| 130 return true; | 178 return true; |
| 131 } | 179 } |
| 132 | 180 |
| 133 // static | 181 // static |
| 134 bool CryptoUtils::ExportKeyingMaterial(StringPiece subkey_secret, | 182 bool CryptoUtils::ExportKeyingMaterial(StringPiece subkey_secret, |
| 135 StringPiece label, | 183 StringPiece label, |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 283 const QuicData& serialized = message.GetSerialized(); | 331 const QuicData& serialized = message.GetSerialized(); |
| 284 std::unique_ptr<crypto::SecureHash> hash( | 332 std::unique_ptr<crypto::SecureHash> hash( |
| 285 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | 333 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
| 286 hash->Update(serialized.data(), serialized.length()); | 334 hash->Update(serialized.data(), serialized.length()); |
| 287 uint8_t digest[32]; | 335 uint8_t digest[32]; |
| 288 hash->Finish(digest, sizeof(digest)); | 336 hash->Finish(digest, sizeof(digest)); |
| 289 output->assign(reinterpret_cast<const char*>(&digest), sizeof(digest)); | 337 output->assign(reinterpret_cast<const char*>(&digest), sizeof(digest)); |
| 290 } | 338 } |
| 291 | 339 |
| 292 } // namespace net | 340 } // namespace net |
| OLD | NEW |