Reduce string copies in Ohttp response logic.
PiperOrigin-RevId: 484546111
diff --git a/quiche/oblivious_http/buffers/oblivious_http_response.cc b/quiche/oblivious_http/buffers/oblivious_http_response.cc
index b81ea8e..ea1936d 100644
--- a/quiche/oblivious_http/buffers/oblivious_http_response.cc
+++ b/quiche/oblivious_http/buffers/oblivious_http_response.cc
@@ -23,22 +23,18 @@
namespace quiche {
namespace {
// Generate a random string.
-std::string random(QuicheRandom* quiche_random, size_t len) {
- std::string token(len, '\0');
+void random(QuicheRandom* quiche_random, char* dest, size_t len) {
if (quiche_random == nullptr) {
quiche_random = QuicheRandom::GetInstance();
}
- quiche_random->RandBytes(token.data(), token.size());
- return token;
+ quiche_random->RandBytes(dest, len);
}
} // namespace
// Ctor.
-ObliviousHttpResponse::ObliviousHttpResponse(std::string resp_nonce,
- std::string resp_ciphertext,
+ObliviousHttpResponse::ObliviousHttpResponse(std::string encrypted_data,
std::string resp_plaintext)
- : response_nonce_(std::move(resp_nonce)),
- response_ciphertext_(std::move(resp_ciphertext)),
+ : encrypted_data_(std::move(encrypted_data)),
response_plaintext_(std::move(resp_plaintext)) {}
// Response Decapsulation.
@@ -50,7 +46,7 @@
// https://www.ietf.org/archive/id/draft-ietf-ohai-ohttp-03.html#section-4.2-4
absl::StatusOr<ObliviousHttpResponse>
ObliviousHttpResponse::CreateClientObliviousResponse(
- absl::string_view encrypted_data,
+ std::string encrypted_data,
ObliviousHttpRequest::Context& oblivious_http_request_context) {
if (oblivious_http_request_context.hpke_context_ == nullptr) {
return absl::FailedPreconditionError(
@@ -87,8 +83,10 @@
}
// Extract response_nonce. Step 2
// https://www.ietf.org/archive/id/draft-ietf-ohai-ohttp-03.html#section-4.2-2.2
- absl::string_view response_nonce = encrypted_data.substr(0, secret_len);
- absl::string_view encrypted_response = encrypted_data.substr(secret_len);
+ absl::string_view response_nonce =
+ absl::string_view(encrypted_data).substr(0, secret_len);
+ absl::string_view encrypted_response =
+ absl::string_view(encrypted_data).substr(secret_len);
// Steps (1, 3 to 5) + AEAD context SetUp before 6th step is performed in
// CommonOperations.
@@ -119,8 +117,7 @@
"Failed to decrypt the response with derived AEAD key and nonce.");
}
decrypted.resize(decrypted_len);
- ObliviousHttpResponse oblivious_response(std::string(response_nonce),
- std::string(encrypted_response),
+ ObliviousHttpResponse oblivious_response(std::move(encrypted_data),
std::move(decrypted));
return oblivious_response;
}
@@ -156,9 +153,17 @@
if (!aead_params_st.ok()) {
return aead_params_st.status();
}
+ const size_t nonce_size = aead_params_st->secret_len;
+ const size_t max_encrypted_data_size =
+ nonce_size + plaintext_payload.size() +
+ EVP_AEAD_max_overhead(EVP_HPKE_AEAD_aead(EVP_HPKE_CTX_aead(
+ oblivious_http_request_context.hpke_context_.get())));
+ std::string encrypted_data(max_encrypted_data_size, '\0');
// response_nonce = random(max(Nn, Nk))
// https://www.ietf.org/archive/id/draft-ietf-ohai-ohttp-03.html#section-4.2-2.2
- std::string response_nonce(random(quiche_random, aead_params_st->secret_len));
+ random(quiche_random, encrypted_data.data(), nonce_size);
+ absl::string_view response_nonce =
+ absl::string_view(encrypted_data).substr(0, nonce_size);
// Steps (1, 3 to 5) + AEAD context SetUp before 6th step is performed in
// CommonOperations.
@@ -172,16 +177,11 @@
// ct = Seal(aead_key, aead_nonce, "", response)
// https://www.ietf.org/archive/id/draft-ietf-ohai-ohttp-03.html#section-4.2-2.6
- std::string ciphertext(
- plaintext_payload.size() +
- EVP_AEAD_max_overhead(EVP_HPKE_AEAD_aead(EVP_HPKE_CTX_aead(
- oblivious_http_request_context.hpke_context_.get()))),
- '\0');
size_t ciphertext_len;
if (!EVP_AEAD_CTX_seal(
common_ops_st.value().aead_ctx.get(),
- reinterpret_cast<uint8_t*>(ciphertext.data()), &ciphertext_len,
- ciphertext.size(),
+ reinterpret_cast<uint8_t*>(encrypted_data.data() + nonce_size),
+ &ciphertext_len, encrypted_data.size() - nonce_size,
reinterpret_cast<const uint8_t*>(
common_ops_st.value().aead_nonce.data()),
aead_params_st.value().aead_nonce_len,
@@ -190,15 +190,14 @@
return SslErrorAsStatus(
"Failed to encrypt the payload with derived AEAD key.");
}
- ciphertext.resize(ciphertext_len);
- if (response_nonce.empty() || ciphertext.empty()) {
+ encrypted_data.resize(nonce_size + ciphertext_len);
+ if (nonce_size == 0 || ciphertext_len == 0) {
return absl::InternalError(absl::StrCat(
"ObliviousHttpResponse Object wasn't initialized with required fields.",
- (response_nonce.empty() ? "Generated nonce is empty." : ""),
- (ciphertext.empty() ? "Generated Encrypted payload is empty." : "")));
+ (nonce_size == 0 ? "Generated nonce is empty." : ""),
+ (ciphertext_len == 0 ? "Generated Encrypted payload is empty." : "")));
}
- ObliviousHttpResponse oblivious_response(std::move(response_nonce),
- std::move(ciphertext),
+ ObliviousHttpResponse oblivious_response(std::move(encrypted_data),
std::move(plaintext_payload));
return oblivious_response;
}
@@ -206,12 +205,12 @@
// Serialize.
// enc_response = concat(response_nonce, ct)
// https://www.ietf.org/archive/id/draft-ietf-ohai-ohttp-03.html#section-4.2-4
-std::string ObliviousHttpResponse::EncapsulateAndSerialize() const {
- return absl::StrCat(response_nonce_, response_ciphertext_);
+const std::string& ObliviousHttpResponse::EncapsulateAndSerialize() const {
+ return encrypted_data_;
}
// Decrypted blob.
-absl::string_view ObliviousHttpResponse::GetPlaintextData() const {
+const std::string& ObliviousHttpResponse::GetPlaintextData() const {
return response_plaintext_;
}
diff --git a/quiche/oblivious_http/buffers/oblivious_http_response.h b/quiche/oblivious_http/buffers/oblivious_http_response.h
index 70198cf..5e3cb0b 100644
--- a/quiche/oblivious_http/buffers/oblivious_http_response.h
+++ b/quiche/oblivious_http/buffers/oblivious_http_response.h
@@ -20,7 +20,7 @@
// @params: Note that `oblivious_http_request_context` is required to stay
// alive only for the lifetime of this factory method call.
static absl::StatusOr<ObliviousHttpResponse> CreateClientObliviousResponse(
- absl::string_view encrypted_data,
+ std::string encrypted_data,
ObliviousHttpRequest::Context& oblivious_http_request_context);
// Encrypt the input param `plaintext_payload` and create OHttp response using
@@ -55,9 +55,9 @@
// Generic Usecase : server-side calls this method in the context of Response
// to serialize OHTTP response that will be returned to client-side.
// Returns serialized OHTTP response bytestring.
- std::string EncapsulateAndSerialize() const;
+ const std::string& EncapsulateAndSerialize() const;
- absl::string_view GetPlaintextData() const;
+ const std::string& GetPlaintextData() const;
private:
struct CommonAeadParamsResult {
@@ -72,8 +72,7 @@
const std::string aead_nonce;
};
- explicit ObliviousHttpResponse(std::string resp_nonce,
- std::string resp_ciphertext,
+ explicit ObliviousHttpResponse(std::string encrypted_data,
std::string resp_plaintext);
// Determines AEAD key len(Nk), AEAD nonce len(Nn) based on HPKE context and
@@ -87,8 +86,7 @@
ObliviousHttpRequest::Context& oblivious_http_request_context,
const size_t aead_key_len, const size_t aead_nonce_len,
const size_t secret_len);
- std::string response_nonce_;
- std::string response_ciphertext_;
+ std::string encrypted_data_;
std::string response_plaintext_;
};