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 |