1 // Copyright (c) 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/crypto/quic_hkdf.h"
6
7 #include <memory>
8
9 #include "absl/strings/string_view.h"
10 #include "openssl/digest.h"
11 #include "openssl/hkdf.h"
12 #include "quiche/quic/platform/api/quic_logging.h"
13
14 namespace quic {
15
16 const size_t kSHA256HashLength = 32;
17 const size_t kMaxKeyMaterialSize = kSHA256HashLength * 256;
18
QuicHKDF(absl::string_view secret,absl::string_view salt,absl::string_view info,size_t key_bytes_to_generate,size_t iv_bytes_to_generate,size_t subkey_secret_bytes_to_generate)19 QuicHKDF::QuicHKDF(absl::string_view secret, absl::string_view salt,
20 absl::string_view info, size_t key_bytes_to_generate,
21 size_t iv_bytes_to_generate,
22 size_t subkey_secret_bytes_to_generate)
23 : QuicHKDF(secret, salt, info, key_bytes_to_generate, key_bytes_to_generate,
24 iv_bytes_to_generate, iv_bytes_to_generate,
25 subkey_secret_bytes_to_generate) {}
26
QuicHKDF(absl::string_view secret,absl::string_view salt,absl::string_view info,size_t client_key_bytes_to_generate,size_t server_key_bytes_to_generate,size_t client_iv_bytes_to_generate,size_t server_iv_bytes_to_generate,size_t subkey_secret_bytes_to_generate)27 QuicHKDF::QuicHKDF(absl::string_view secret, absl::string_view salt,
28 absl::string_view info, size_t client_key_bytes_to_generate,
29 size_t server_key_bytes_to_generate,
30 size_t client_iv_bytes_to_generate,
31 size_t server_iv_bytes_to_generate,
32 size_t subkey_secret_bytes_to_generate) {
33 const size_t material_length =
34 2 * client_key_bytes_to_generate + client_iv_bytes_to_generate +
35 2 * server_key_bytes_to_generate + server_iv_bytes_to_generate +
36 subkey_secret_bytes_to_generate;
37 QUICHE_DCHECK_LT(material_length, kMaxKeyMaterialSize);
38
39 output_.resize(material_length);
40 // On Windows, when the size of output_ is zero, dereference of 0'th element
41 // results in a crash. C++11 solves this problem by adding a data() getter
42 // method to std::vector.
43 if (output_.empty()) {
44 return;
45 }
46
47 ::HKDF(&output_[0], output_.size(), ::EVP_sha256(),
48 reinterpret_cast<const uint8_t*>(secret.data()), secret.size(),
49 reinterpret_cast<const uint8_t*>(salt.data()), salt.size(),
50 reinterpret_cast<const uint8_t*>(info.data()), info.size());
51
52 size_t j = 0;
53 if (client_key_bytes_to_generate) {
54 client_write_key_ = absl::string_view(reinterpret_cast<char*>(&output_[j]),
55 client_key_bytes_to_generate);
56 j += client_key_bytes_to_generate;
57 }
58
59 if (server_key_bytes_to_generate) {
60 server_write_key_ = absl::string_view(reinterpret_cast<char*>(&output_[j]),
61 server_key_bytes_to_generate);
62 j += server_key_bytes_to_generate;
63 }
64
65 if (client_iv_bytes_to_generate) {
66 client_write_iv_ = absl::string_view(reinterpret_cast<char*>(&output_[j]),
67 client_iv_bytes_to_generate);
68 j += client_iv_bytes_to_generate;
69 }
70
71 if (server_iv_bytes_to_generate) {
72 server_write_iv_ = absl::string_view(reinterpret_cast<char*>(&output_[j]),
73 server_iv_bytes_to_generate);
74 j += server_iv_bytes_to_generate;
75 }
76
77 if (subkey_secret_bytes_to_generate) {
78 subkey_secret_ = absl::string_view(reinterpret_cast<char*>(&output_[j]),
79 subkey_secret_bytes_to_generate);
80 j += subkey_secret_bytes_to_generate;
81 }
82 // Repeat client and server key bytes for header protection keys.
83 if (client_key_bytes_to_generate) {
84 client_hp_key_ = absl::string_view(reinterpret_cast<char*>(&output_[j]),
85 client_key_bytes_to_generate);
86 j += client_key_bytes_to_generate;
87 }
88
89 if (server_key_bytes_to_generate) {
90 server_hp_key_ = absl::string_view(reinterpret_cast<char*>(&output_[j]),
91 server_key_bytes_to_generate);
92 j += server_key_bytes_to_generate;
93 }
94 }
95
~QuicHKDF()96 QuicHKDF::~QuicHKDF() {}
97
98 } // namespace quic
99