Use Span in QUIC-LB EncryptionPass()
PiperOrigin-RevId: 441529229
diff --git a/quiche/quic/load_balancer/load_balancer_config.cc b/quiche/quic/load_balancer/load_balancer_config.cc
index b0c161f..56669e0 100644
--- a/quiche/quic/load_balancer/load_balancer_config.cc
+++ b/quiche/quic/load_balancer/load_balancer_config.cc
@@ -137,25 +137,25 @@
: absl::optional<LoadBalancerConfig>();
}
-bool LoadBalancerConfig::EncryptionPass(uint8_t *target,
+bool LoadBalancerConfig::EncryptionPass(absl::Span<uint8_t> target,
const uint8_t index) const {
uint8_t buf[kLoadBalancerBlockSize];
- if (!key_.has_value() || target == nullptr) {
+ if (!key_.has_value() || target.size() < plaintext_len()) {
return false;
}
if (index % 2) { // Odd indices go from left to right
- TakePlaintextFromLeft(buf, target, plaintext_len(), index);
+ TakePlaintextFromLeft(buf, target.data(), plaintext_len(), index);
} else {
- TakePlaintextFromRight(buf, target, plaintext_len(), index);
+ TakePlaintextFromRight(buf, target.data(), plaintext_len(), index);
}
if (!BlockEncrypt(buf, buf)) {
return false;
}
// XOR bits over the correct half.
if (index % 2) {
- CiphertextXorWithRight(target, buf, plaintext_len());
+ CiphertextXorWithRight(target.data(), buf, plaintext_len());
} else {
- CiphertextXorWithLeft(target, buf, plaintext_len());
+ CiphertextXorWithLeft(target.data(), buf, plaintext_len());
}
return true;
}
diff --git a/quiche/quic/load_balancer/load_balancer_config.h b/quiche/quic/load_balancer/load_balancer_config.h
index 251cd3a..bc92d5f 100644
--- a/quiche/quic/load_balancer/load_balancer_config.h
+++ b/quiche/quic/load_balancer/load_balancer_config.h
@@ -47,8 +47,9 @@
// Handles one pass of 4-pass encryption. Encoder and decoder use of this
// function varies substantially, so they are not implemented here.
- // Returns false if the config is not encrypted.
- ABSL_MUST_USE_RESULT bool EncryptionPass(uint8_t *target,
+ // Returns false if the config is not encrypted, or if |target| isn't long
+ // enough.
+ ABSL_MUST_USE_RESULT bool EncryptionPass(absl::Span<uint8_t> target,
const uint8_t index) const;
// Use the key to do a block encryption, which is used both in all cases of
// encrypted configs. Returns false if there's no key.
diff --git a/quiche/quic/load_balancer/load_balancer_config_test.cc b/quiche/quic/load_balancer/load_balancer_config_test.cc
index 8c58c5d..f59a3be 100644
--- a/quiche/quic/load_balancer/load_balancer_config_test.cc
+++ b/quiche/quic/load_balancer/load_balancer_config_test.cc
@@ -4,6 +4,9 @@
#include "quiche/quic/load_balancer/load_balancer_config.h"
+#include <cstdint>
+
+#include "absl/types/span.h"
#include "quiche/quic/platform/api/quic_expect_bug.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/test_tools/quic_test_utils.h"
@@ -91,27 +94,26 @@
std::array<uint8_t, 7> bytes = {
0x31, 0x44, 0x1a, 0x9c, 0x69, 0xc2, 0x75,
};
- EXPECT_FALSE(config->EncryptionPass(nullptr, 0));
- EXPECT_TRUE(config->EncryptionPass(bytes.data(), 1));
+ // Input is too short.
+ EXPECT_FALSE(config->EncryptionPass(absl::Span<uint8_t>(bytes.data(), 6), 0));
+ EXPECT_TRUE(config->EncryptionPass(absl::Span<uint8_t>(bytes), 1));
EXPECT_TRUE((bytes == std::array<uint8_t, 7>(
{0x31, 0x44, 0x1a, 0x9d, 0xbc, 0x04, 0x26})));
- EXPECT_TRUE(config->EncryptionPass(bytes.data(), 2));
+ EXPECT_TRUE(config->EncryptionPass(absl::Span<uint8_t>(bytes), 2));
EXPECT_TRUE((bytes == std::array<uint8_t, 7>(
{0x4f, 0xdd, 0x0c, 0x9d, 0xbc, 0x04, 0x26})));
- EXPECT_TRUE(config->EncryptionPass(bytes.data(), 3));
+ EXPECT_TRUE(config->EncryptionPass(absl::Span<uint8_t>(bytes), 3));
EXPECT_TRUE((bytes == std::array<uint8_t, 7>(
{0x4f, 0xdd, 0x0c, 0x9b, 0xba, 0x1e, 0xe0})));
- EXPECT_TRUE(config->EncryptionPass(bytes.data(), 4));
+ EXPECT_TRUE(config->EncryptionPass(absl::Span<uint8_t>(bytes), 4));
EXPECT_TRUE((bytes == std::array<uint8_t, 7>(
{0xe2, 0x3c, 0xb4, 0x2b, 0xba, 0x1e, 0xe0})));
}
TEST_F(LoadBalancerConfigTest, EncryptionPassPlaintext) {
auto config = LoadBalancerConfig::CreateUnencrypted(0, 3, 4);
- std::array<uint8_t, 7> bytes = {
- 0x31, 0x44, 0x1a, 0x9c, 0x69, 0xc2, 0x75,
- };
- EXPECT_FALSE(config->EncryptionPass(bytes.data(), 1));
+ std::array<uint8_t, 7> bytes = {0x31, 0x44, 0x1a, 0x9c, 0x69, 0xc2, 0x75};
+ EXPECT_FALSE(config->EncryptionPass(absl::Span<uint8_t>(bytes), 1));
}
TEST_F(LoadBalancerConfigTest, InvalidBlockEncryption) {
@@ -119,7 +121,7 @@
auto pt_config = LoadBalancerConfig::CreateUnencrypted(0, 8, 8);
EXPECT_FALSE(pt_config->BlockEncrypt(pt, ct));
EXPECT_FALSE(pt_config->BlockDecrypt(ct, pt));
- EXPECT_FALSE(pt_config->EncryptionPass(pt, 0));
+ EXPECT_FALSE(pt_config->EncryptionPass(absl::Span<uint8_t>(pt), 0));
auto small_cid_config =
LoadBalancerConfig::Create(0, 3, 4, absl::string_view(raw_key, 16));
EXPECT_TRUE(small_cid_config->BlockEncrypt(pt, ct));
diff --git a/quiche/quic/load_balancer/load_balancer_decoder.cc b/quiche/quic/load_balancer/load_balancer_decoder.cc
index 4f328e8..a946b36 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder.cc
+++ b/quiche/quic/load_balancer/load_balancer_decoder.cc
@@ -61,7 +61,7 @@
memcpy(result, data, config->plaintext_len());
uint8_t end = (config->server_id_len() > config->nonce_len()) ? 1 : 2;
for (uint8_t i = kNumLoadBalancerCryptoPasses; i >= end; i--) {
- if (!config->EncryptionPass(result, i)) {
+ if (!config->EncryptionPass(absl::Span<uint8_t>(result), i)) {
return absl::optional<LoadBalancerServerId>();
}
}
diff --git a/quiche/quic/load_balancer/load_balancer_encoder.cc b/quiche/quic/load_balancer/load_balancer_encoder.cc
index 6a4655c..bb9608b 100644
--- a/quiche/quic/load_balancer/load_balancer_encoder.cc
+++ b/quiche/quic/load_balancer/load_balancer_encoder.cc
@@ -154,7 +154,8 @@
}
} else {
for (uint8_t i = 1; i <= kNumLoadBalancerCryptoPasses; i++) {
- if (!config_->EncryptionPass(block_start, i)) {
+ if (!config_->EncryptionPass(absl::Span<uint8_t>(block_start, length - 1),
+ i)) {
QUIC_LOG(ERROR) << "Block encryption failed";
return QuicConnectionId();
}