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/core/crypto/crypto_utils.h" | 5 #include "net/quic/core/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 "net/quic/core/crypto/crypto_handshake.h" | 10 #include "net/quic/core/crypto/crypto_handshake.h" |
11 #include "net/quic/core/crypto/crypto_protocol.h" | 11 #include "net/quic/core/crypto/crypto_protocol.h" |
12 #include "net/quic/core/crypto/quic_decrypter.h" | 12 #include "net/quic/core/crypto/quic_decrypter.h" |
13 #include "net/quic/core/crypto/quic_encrypter.h" | 13 #include "net/quic/core/crypto/quic_encrypter.h" |
14 #include "net/quic/core/crypto/quic_random.h" | 14 #include "net/quic/core/crypto/quic_random.h" |
15 #include "net/quic/core/quic_time.h" | 15 #include "net/quic/core/quic_time.h" |
16 #include "net/quic/core/quic_utils.h" | 16 #include "net/quic/core/quic_utils.h" |
17 #include "net/quic/platform/api/quic_bug_tracker.h" | 17 #include "net/quic/platform/api/quic_bug_tracker.h" |
18 #include "net/quic/platform/api/quic_logging.h" | 18 #include "net/quic/platform/api/quic_logging.h" |
19 #include "third_party/boringssl/src/include/openssl/sha.h" | 19 #include "third_party/boringssl/src/include/openssl/sha.h" |
20 | 20 |
21 using base::StringPiece; | |
22 using std::string; | 21 using std::string; |
23 | 22 |
24 namespace net { | 23 namespace net { |
25 | 24 |
26 // static | 25 // static |
27 void CryptoUtils::GenerateNonce(QuicWallTime now, | 26 void CryptoUtils::GenerateNonce(QuicWallTime now, |
28 QuicRandom* random_generator, | 27 QuicRandom* random_generator, |
29 StringPiece orbit, | 28 QuicStringPiece orbit, |
30 string* nonce) { | 29 string* nonce) { |
31 // a 4-byte timestamp + 28 random bytes. | 30 // a 4-byte timestamp + 28 random bytes. |
32 nonce->reserve(kNonceSize); | 31 nonce->reserve(kNonceSize); |
33 nonce->resize(kNonceSize); | 32 nonce->resize(kNonceSize); |
34 | 33 |
35 uint32_t gmt_unix_time = static_cast<uint32_t>(now.ToUNIXSeconds()); | 34 uint32_t gmt_unix_time = static_cast<uint32_t>(now.ToUNIXSeconds()); |
36 // The time in the nonce must be encoded in big-endian because the | 35 // The time in the nonce must be encoded in big-endian because the |
37 // strike-register depends on the nonces being ordered by time. | 36 // strike-register depends on the nonces being ordered by time. |
38 (*nonce)[0] = static_cast<char>(gmt_unix_time >> 24); | 37 (*nonce)[0] = static_cast<char>(gmt_unix_time >> 24); |
39 (*nonce)[1] = static_cast<char>(gmt_unix_time >> 16); | 38 (*nonce)[1] = static_cast<char>(gmt_unix_time >> 16); |
40 (*nonce)[2] = static_cast<char>(gmt_unix_time >> 8); | 39 (*nonce)[2] = static_cast<char>(gmt_unix_time >> 8); |
41 (*nonce)[3] = static_cast<char>(gmt_unix_time); | 40 (*nonce)[3] = static_cast<char>(gmt_unix_time); |
42 size_t bytes_written = 4; | 41 size_t bytes_written = 4; |
43 | 42 |
44 if (orbit.size() == 8) { | 43 if (orbit.size() == 8) { |
45 memcpy(&(*nonce)[bytes_written], orbit.data(), orbit.size()); | 44 memcpy(&(*nonce)[bytes_written], orbit.data(), orbit.size()); |
46 bytes_written += orbit.size(); | 45 bytes_written += orbit.size(); |
47 } | 46 } |
48 | 47 |
49 random_generator->RandBytes(&(*nonce)[bytes_written], | 48 random_generator->RandBytes(&(*nonce)[bytes_written], |
50 kNonceSize - bytes_written); | 49 kNonceSize - bytes_written); |
51 } | 50 } |
52 | 51 |
53 // static | 52 // static |
54 bool CryptoUtils::DeriveKeys(StringPiece premaster_secret, | 53 bool CryptoUtils::DeriveKeys(QuicStringPiece premaster_secret, |
55 QuicTag aead, | 54 QuicTag aead, |
56 StringPiece client_nonce, | 55 QuicStringPiece client_nonce, |
57 StringPiece server_nonce, | 56 QuicStringPiece server_nonce, |
58 const string& hkdf_input, | 57 const string& hkdf_input, |
59 Perspective perspective, | 58 Perspective perspective, |
60 Diversification diversification, | 59 Diversification diversification, |
61 CrypterPair* crypters, | 60 CrypterPair* crypters, |
62 string* subkey_secret) { | 61 string* subkey_secret) { |
63 crypters->encrypter.reset(QuicEncrypter::Create(aead)); | 62 crypters->encrypter.reset(QuicEncrypter::Create(aead)); |
64 crypters->decrypter.reset(QuicDecrypter::Create(aead)); | 63 crypters->decrypter.reset(QuicDecrypter::Create(aead)); |
65 size_t key_bytes = crypters->encrypter->GetKeySize(); | 64 size_t key_bytes = crypters->encrypter->GetKeySize(); |
66 size_t nonce_prefix_bytes = crypters->encrypter->GetNoncePrefixSize(); | 65 size_t nonce_prefix_bytes = crypters->encrypter->GetNoncePrefixSize(); |
67 size_t subkey_secret_bytes = | 66 size_t subkey_secret_bytes = |
68 subkey_secret == nullptr ? 0 : premaster_secret.length(); | 67 subkey_secret == nullptr ? 0 : premaster_secret.length(); |
69 | 68 |
70 StringPiece nonce = client_nonce; | 69 QuicStringPiece nonce = client_nonce; |
71 string nonce_storage; | 70 string nonce_storage; |
72 if (!server_nonce.empty()) { | 71 if (!server_nonce.empty()) { |
73 nonce_storage = client_nonce.as_string() + server_nonce.as_string(); | 72 nonce_storage = client_nonce.as_string() + server_nonce.as_string(); |
74 nonce = nonce_storage; | 73 nonce = nonce_storage; |
75 } | 74 } |
76 | 75 |
77 crypto::HKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes, | 76 crypto::HKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes, |
78 nonce_prefix_bytes, subkey_secret_bytes); | 77 nonce_prefix_bytes, subkey_secret_bytes); |
79 | 78 |
80 // Key derivation depends on the key diversification method being employed. | 79 // Key derivation depends on the key diversification method being employed. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 } | 137 } |
139 | 138 |
140 if (subkey_secret != nullptr) { | 139 if (subkey_secret != nullptr) { |
141 hkdf.subkey_secret().CopyToString(subkey_secret); | 140 hkdf.subkey_secret().CopyToString(subkey_secret); |
142 } | 141 } |
143 | 142 |
144 return true; | 143 return true; |
145 } | 144 } |
146 | 145 |
147 // static | 146 // static |
148 bool CryptoUtils::ExportKeyingMaterial(StringPiece subkey_secret, | 147 bool CryptoUtils::ExportKeyingMaterial(QuicStringPiece subkey_secret, |
149 StringPiece label, | 148 QuicStringPiece label, |
150 StringPiece context, | 149 QuicStringPiece context, |
151 size_t result_len, | 150 size_t result_len, |
152 string* result) { | 151 string* result) { |
153 for (size_t i = 0; i < label.length(); i++) { | 152 for (size_t i = 0; i < label.length(); i++) { |
154 if (label[i] == '\0') { | 153 if (label[i] == '\0') { |
155 QUIC_LOG(ERROR) << "ExportKeyingMaterial label may not contain NULs"; | 154 QUIC_LOG(ERROR) << "ExportKeyingMaterial label may not contain NULs"; |
156 return false; | 155 return false; |
157 } | 156 } |
158 } | 157 } |
159 // Create HKDF info input: null-terminated label + length-prefixed context | 158 // Create HKDF info input: null-terminated label + length-prefixed context |
160 if (context.length() >= std::numeric_limits<uint32_t>::max()) { | 159 if (context.length() >= std::numeric_limits<uint32_t>::max()) { |
161 QUIC_LOG(ERROR) << "Context value longer than 2^32"; | 160 QUIC_LOG(ERROR) << "Context value longer than 2^32"; |
162 return false; | 161 return false; |
163 } | 162 } |
164 uint32_t context_length = static_cast<uint32_t>(context.length()); | 163 uint32_t context_length = static_cast<uint32_t>(context.length()); |
165 string info = label.as_string(); | 164 string info = label.as_string(); |
166 info.push_back('\0'); | 165 info.push_back('\0'); |
167 info.append(reinterpret_cast<char*>(&context_length), sizeof(context_length)); | 166 info.append(reinterpret_cast<char*>(&context_length), sizeof(context_length)); |
168 info.append(context.data(), context.length()); | 167 info.append(context.data(), context.length()); |
169 | 168 |
170 crypto::HKDF hkdf(subkey_secret, StringPiece() /* no salt */, info, | 169 crypto::HKDF hkdf(subkey_secret, QuicStringPiece() /* no salt */, info, |
171 result_len, 0 /* no fixed IV */, 0 /* no subkey secret */); | 170 result_len, 0 /* no fixed IV */, 0 /* no subkey secret */); |
172 hkdf.client_write_key().CopyToString(result); | 171 hkdf.client_write_key().CopyToString(result); |
173 return true; | 172 return true; |
174 } | 173 } |
175 | 174 |
176 // static | 175 // static |
177 uint64_t CryptoUtils::ComputeLeafCertHash(StringPiece cert) { | 176 uint64_t CryptoUtils::ComputeLeafCertHash(QuicStringPiece cert) { |
178 return QuicUtils::FNV1a_64_Hash(cert); | 177 return QuicUtils::FNV1a_64_Hash(cert); |
179 } | 178 } |
180 | 179 |
181 QuicErrorCode CryptoUtils::ValidateServerHello( | 180 QuicErrorCode CryptoUtils::ValidateServerHello( |
182 const CryptoHandshakeMessage& server_hello, | 181 const CryptoHandshakeMessage& server_hello, |
183 const QuicVersionVector& negotiated_versions, | 182 const QuicVersionVector& negotiated_versions, |
184 string* error_details) { | 183 string* error_details) { |
185 DCHECK(error_details != nullptr); | 184 DCHECK(error_details != nullptr); |
186 | 185 |
187 if (server_hello.tag() != kSHLO) { | 186 if (server_hello.tag() != kSHLO) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 void CryptoUtils::HashHandshakeMessage(const CryptoHandshakeMessage& message, | 294 void CryptoUtils::HashHandshakeMessage(const CryptoHandshakeMessage& message, |
296 string* output) { | 295 string* output) { |
297 const QuicData& serialized = message.GetSerialized(); | 296 const QuicData& serialized = message.GetSerialized(); |
298 uint8_t digest[SHA256_DIGEST_LENGTH]; | 297 uint8_t digest[SHA256_DIGEST_LENGTH]; |
299 SHA256(reinterpret_cast<const uint8_t*>(serialized.data()), | 298 SHA256(reinterpret_cast<const uint8_t*>(serialized.data()), |
300 serialized.length(), digest); | 299 serialized.length(), digest); |
301 output->assign(reinterpret_cast<const char*>(digest), sizeof(digest)); | 300 output->assign(reinterpret_cast<const char*>(digest), sizeof(digest)); |
302 } | 301 } |
303 | 302 |
304 } // namespace net | 303 } // namespace net |
OLD | NEW |