xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/aead_base_decrypter.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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