Large chunked OHTTP request fix (#36766)
The RFC suggests a maximum chunk size of 16,384 bytes. If a request is made with a plaintext length that is greater than the limit, split it up into 15kb chunks and encrypt them individually.
This commit is contained in:
@@ -11,6 +11,10 @@
|
||||
|
||||
namespace oblivious_http {
|
||||
|
||||
namespace {
|
||||
constexpr size_t kMaxEncryptChunkSize = 16384;
|
||||
} // namespace
|
||||
|
||||
ObliviousHttpChunkProcessor::ObliviousHttpChunkProcessor(
|
||||
mojo::PendingRemote<network::mojom::ObliviousHttpChunkClient>
|
||||
chunk_client_remote,
|
||||
@@ -55,12 +59,19 @@ ObliviousHttpChunkProcessor::Create(
|
||||
std::optional<std::string> ObliviousHttpChunkProcessor::EncryptRequest(
|
||||
std::string_view plaintext) {
|
||||
CHECK(ohttp_client_);
|
||||
auto result =
|
||||
ohttp_client_->EncryptRequestChunk(plaintext, /*is_final_chunk=*/true);
|
||||
if (!result.ok()) {
|
||||
return std::nullopt;
|
||||
|
||||
std::string result;
|
||||
for (size_t offset = 0; offset < plaintext.size();
|
||||
offset += kMaxEncryptChunkSize) {
|
||||
const bool is_final = offset + kMaxEncryptChunkSize >= plaintext.size();
|
||||
const auto chunk = plaintext.substr(offset, kMaxEncryptChunkSize);
|
||||
auto encrypted = ohttp_client_->EncryptRequestChunk(chunk, is_final);
|
||||
if (!encrypted.ok()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
result += std::move(*encrypted);
|
||||
}
|
||||
return std::move(*result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void ObliviousHttpChunkProcessor::OnDataReceived(std::string_view data,
|
||||
|
||||
@@ -161,12 +161,13 @@ class ObliviousHttpChunkProcessorTest
|
||||
return result;
|
||||
}
|
||||
|
||||
void EncryptRequestAndGatewayDecrypt() {
|
||||
auto encrypted_request = processor_->EncryptRequest(kTestRequestBody);
|
||||
void EncryptRequestAndGatewayDecrypt(
|
||||
std::string_view request_body = kTestRequestBody) {
|
||||
auto encrypted_request = processor_->EncryptRequest(request_body);
|
||||
ASSERT_TRUE(encrypted_request.has_value());
|
||||
ASSERT_TRUE(
|
||||
gateway_->DecryptRequest(*encrypted_request, /*end_stream=*/true).ok());
|
||||
EXPECT_EQ(kTestRequestBody, received_client_request_body_);
|
||||
EXPECT_EQ(request_body, received_client_request_body_);
|
||||
}
|
||||
|
||||
// Drives a full round-trip: encrypts kTestRequestBody, feeds the simulated
|
||||
@@ -233,6 +234,18 @@ TEST_F(ObliviousHttpChunkProcessorTest,
|
||||
EncryptRequestAndGatewayDecrypt();
|
||||
}
|
||||
|
||||
TEST_F(ObliviousHttpChunkProcessorTest,
|
||||
EncryptRequest_LargeRequest_GatewayDecryptsCorrectly) {
|
||||
constexpr std::string_view kAlphabet = "abcdefghijklmnopqrstuvwxyz";
|
||||
constexpr size_t kLargeRequestSize = 50000;
|
||||
std::string large_request;
|
||||
large_request.reserve(kLargeRequestSize);
|
||||
while (large_request.size() < kLargeRequestSize) {
|
||||
large_request += kAlphabet;
|
||||
}
|
||||
EncryptRequestAndGatewayDecrypt(large_request);
|
||||
}
|
||||
|
||||
TEST_F(ObliviousHttpChunkProcessorTest,
|
||||
RoundTrip_BodyChunksDeliveredToChunkClient) {
|
||||
auto future = RunRoundTrip("hello chunked", net::HTTP_OK,
|
||||
|
||||
Reference in New Issue
Block a user