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_; };