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
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/crypto/aead_base_decrypter.h"
6
7 #include <cstdint>
8 #include <string>
9
10 #include "absl/base/macros.h"
11 #include "absl/strings/string_view.h"
12 #include "openssl/crypto.h"
13 #include "openssl/err.h"
14 #include "openssl/evp.h"
15 #include "quiche/quic/core/quic_utils.h"
16 #include "quiche/quic/platform/api/quic_bug_tracker.h"
17 #include "quiche/quic/platform/api/quic_logging.h"
18 #include "quiche/common/quiche_crypto_logging.h"
19
20 namespace quic {
21 using ::quiche::ClearOpenSslErrors;
22 using ::quiche::DLogOpenSslErrors;
23 namespace {
24
InitAndCall(const EVP_AEAD * (* aead_getter)())25 const EVP_AEAD* InitAndCall(const EVP_AEAD* (*aead_getter)()) {
26 // Ensure BoringSSL is initialized before calling |aead_getter|. In Chromium,
27 // the static initializer is disabled.
28 CRYPTO_library_init();
29 return aead_getter();
30 }
31
32 } // namespace
33
AeadBaseDecrypter(const EVP_AEAD * (* aead_getter)(),size_t key_size,size_t auth_tag_size,size_t nonce_size,bool use_ietf_nonce_construction)34 AeadBaseDecrypter::AeadBaseDecrypter(const EVP_AEAD* (*aead_getter)(),
35 size_t key_size, size_t auth_tag_size,
36 size_t nonce_size,
37 bool use_ietf_nonce_construction)
38 : aead_alg_(InitAndCall(aead_getter)),
39 key_size_(key_size),
40 auth_tag_size_(auth_tag_size),
41 nonce_size_(nonce_size),
42 use_ietf_nonce_construction_(use_ietf_nonce_construction),
43 have_preliminary_key_(false) {
44 QUICHE_DCHECK_GT(256u, key_size);
45 QUICHE_DCHECK_GT(256u, auth_tag_size);
46 QUICHE_DCHECK_GT(256u, nonce_size);
47 QUICHE_DCHECK_LE(key_size_, sizeof(key_));
48 QUICHE_DCHECK_LE(nonce_size_, sizeof(iv_));
49 }
50
~AeadBaseDecrypter()51 AeadBaseDecrypter::~AeadBaseDecrypter() {}
52
SetKey(absl::string_view key)53 bool AeadBaseDecrypter::SetKey(absl::string_view key) {
54 QUICHE_DCHECK_EQ(key.size(), key_size_);
55 if (key.size() != key_size_) {
56 return false;
57 }
58 memcpy(key_, key.data(), key.size());
59
60 EVP_AEAD_CTX_cleanup(ctx_.get());
61 if (!EVP_AEAD_CTX_init(ctx_.get(), aead_alg_, key_, key_size_, auth_tag_size_,
62 nullptr)) {
63 DLogOpenSslErrors();
64 return false;
65 }
66
67 return true;
68 }
69
SetNoncePrefix(absl::string_view nonce_prefix)70 bool AeadBaseDecrypter::SetNoncePrefix(absl::string_view nonce_prefix) {
71 if (use_ietf_nonce_construction_) {
72 QUIC_BUG(quic_bug_10709_1)
73 << "Attempted to set nonce prefix on IETF QUIC crypter";
74 return false;
75 }
76 QUICHE_DCHECK_EQ(nonce_prefix.size(), nonce_size_ - sizeof(QuicPacketNumber));
77 if (nonce_prefix.size() != nonce_size_ - sizeof(QuicPacketNumber)) {
78 return false;
79 }
80 memcpy(iv_, nonce_prefix.data(), nonce_prefix.size());
81 return true;
82 }
83
SetIV(absl::string_view iv)84 bool AeadBaseDecrypter::SetIV(absl::string_view iv) {
85 if (!use_ietf_nonce_construction_) {
86 QUIC_BUG(quic_bug_10709_2) << "Attempted to set IV on Google QUIC crypter";
87 return false;
88 }
89 QUICHE_DCHECK_EQ(iv.size(), nonce_size_);
90 if (iv.size() != nonce_size_) {
91 return false;
92 }
93 memcpy(iv_, iv.data(), iv.size());
94 return true;
95 }
96
SetPreliminaryKey(absl::string_view key)97 bool AeadBaseDecrypter::SetPreliminaryKey(absl::string_view key) {
98 QUICHE_DCHECK(!have_preliminary_key_);
99 SetKey(key);
100 have_preliminary_key_ = true;
101
102 return true;
103 }
104
SetDiversificationNonce(const DiversificationNonce & nonce)105 bool AeadBaseDecrypter::SetDiversificationNonce(
106 const DiversificationNonce& nonce) {
107 if (!have_preliminary_key_) {
108 return true;
109 }
110
111 std::string key, nonce_prefix;
112 size_t prefix_size = nonce_size_;
113 if (!use_ietf_nonce_construction_) {
114 prefix_size -= sizeof(QuicPacketNumber);
115 }
116 DiversifyPreliminaryKey(
117 absl::string_view(reinterpret_cast<const char*>(key_), key_size_),
118 absl::string_view(reinterpret_cast<const char*>(iv_), prefix_size), nonce,
119 key_size_, prefix_size, &key, &nonce_prefix);
120
121 if (!SetKey(key) ||
122 (!use_ietf_nonce_construction_ && !SetNoncePrefix(nonce_prefix)) ||
123 (use_ietf_nonce_construction_ && !SetIV(nonce_prefix))) {
124 QUICHE_DCHECK(false);
125 return false;
126 }
127
128 have_preliminary_key_ = false;
129 return true;
130 }
131
DecryptPacket(uint64_t packet_number,absl::string_view associated_data,absl::string_view ciphertext,char * output,size_t * output_length,size_t max_output_length)132 bool AeadBaseDecrypter::DecryptPacket(uint64_t packet_number,
133 absl::string_view associated_data,
134 absl::string_view ciphertext,
135 char* output, size_t* output_length,
136 size_t max_output_length) {
137 if (ciphertext.length() < auth_tag_size_) {
138 return false;
139 }
140
141 if (have_preliminary_key_) {
142 QUIC_BUG(quic_bug_10709_3)
143 << "Unable to decrypt while key diversification is pending";
144 return false;
145 }
146
147 uint8_t nonce[kMaxNonceSize];
148 memcpy(nonce, iv_, nonce_size_);
149 size_t prefix_len = nonce_size_ - sizeof(packet_number);
150 if (use_ietf_nonce_construction_) {
151 for (size_t i = 0; i < sizeof(packet_number); ++i) {
152 nonce[prefix_len + i] ^=
153 (packet_number >> ((sizeof(packet_number) - i - 1) * 8)) & 0xff;
154 }
155 } else {
156 memcpy(nonce + prefix_len, &packet_number, sizeof(packet_number));
157 }
158 if (!EVP_AEAD_CTX_open(
159 ctx_.get(), reinterpret_cast<uint8_t*>(output), output_length,
160 max_output_length, reinterpret_cast<const uint8_t*>(nonce),
161 nonce_size_, reinterpret_cast<const uint8_t*>(ciphertext.data()),
162 ciphertext.size(),
163 reinterpret_cast<const uint8_t*>(associated_data.data()),
164 associated_data.size())) {
165 // Because QuicFramer does trial decryption, decryption errors are expected
166 // when encryption level changes. So we don't log decryption errors.
167 ClearOpenSslErrors();
168 return false;
169 }
170 return true;
171 }
172
GetKeySize() const173 size_t AeadBaseDecrypter::GetKeySize() const { return key_size_; }
174
GetNoncePrefixSize() const175 size_t AeadBaseDecrypter::GetNoncePrefixSize() const {
176 return nonce_size_ - sizeof(QuicPacketNumber);
177 }
178
GetIVSize() const179 size_t AeadBaseDecrypter::GetIVSize() const { return nonce_size_; }
180
GetKey() const181 absl::string_view AeadBaseDecrypter::GetKey() const {
182 return absl::string_view(reinterpret_cast<const char*>(key_), key_size_);
183 }
184
GetNoncePrefix() const185 absl::string_view AeadBaseDecrypter::GetNoncePrefix() const {
186 return absl::string_view(reinterpret_cast<const char*>(iv_),
187 nonce_size_ - sizeof(QuicPacketNumber));
188 }
189
190 } // namespace quic
191