| #include "quiche/oblivious_http/oblivious_http_client.h" |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/str_cat.h" |
| #include "absl/strings/string_view.h" |
| #include "quiche/common/quiche_crypto_logging.h" |
| |
| namespace quiche { |
| |
| namespace { |
| |
| // Use BoringSSL's setup_sender API to validate whether the HPKE public key |
| // input provided by the user is valid. |
| absl::Status ValidateClientParameters( |
| absl::string_view hpke_public_key, |
| const ObliviousHttpHeaderKeyConfig& ohttp_key_config) { |
| // Initialize HPKE client context and check if context can be setup with the |
| // given public key to verify if the public key is indeed valid. |
| bssl::UniquePtr<EVP_HPKE_CTX> client_ctx(EVP_HPKE_CTX_new()); |
| if (client_ctx == nullptr) { |
| return SslErrorAsStatus( |
| "Failed to initialize HPKE ObliviousHttpClient Context."); |
| } |
| // Setup the sender (client) |
| std::string encapsulated_key(EVP_HPKE_MAX_ENC_LENGTH, '\0'); |
| size_t enc_len; |
| absl::string_view info = "verify if given HPKE public key is valid"; |
| if (!EVP_HPKE_CTX_setup_sender( |
| client_ctx.get(), reinterpret_cast<uint8_t*>(encapsulated_key.data()), |
| &enc_len, encapsulated_key.size(), ohttp_key_config.GetHpkeKem(), |
| ohttp_key_config.GetHpkeKdf(), ohttp_key_config.GetHpkeAead(), |
| reinterpret_cast<const uint8_t*>(hpke_public_key.data()), |
| hpke_public_key.size(), reinterpret_cast<const uint8_t*>(info.data()), |
| info.size())) { |
| return SslErrorAsStatus( |
| "Failed to setup HPKE context with given public key param " |
| "hpke_public_key."); |
| } |
| return absl::OkStatus(); |
| } |
| |
| } // namespace |
| |
| // Constructor. |
| ObliviousHttpClient::ObliviousHttpClient( |
| std::string client_public_key, |
| const ObliviousHttpHeaderKeyConfig& ohttp_key_config) |
| : hpke_public_key_(std::move(client_public_key)), |
| ohttp_key_config_(ohttp_key_config) {} |
| |
| // Initialize Bssl. |
| absl::StatusOr<ObliviousHttpClient> ObliviousHttpClient::Create( |
| absl::string_view hpke_public_key, |
| const ObliviousHttpHeaderKeyConfig& ohttp_key_config) { |
| if (hpke_public_key.empty()) { |
| return absl::InvalidArgumentError("Invalid/Empty HPKE public key."); |
| } |
| auto is_valid_input = |
| ValidateClientParameters(hpke_public_key, ohttp_key_config); |
| if (!is_valid_input.ok()) { |
| return absl::InvalidArgumentError( |
| absl::StrCat("Invalid input received in method parameters. ", |
| is_valid_input.message())); |
| } |
| return ObliviousHttpClient(std::string(hpke_public_key), ohttp_key_config); |
| } |
| |
| absl::StatusOr<ObliviousHttpRequest> |
| ObliviousHttpClient::CreateObliviousHttpRequest( |
| std::string plaintext_data) const { |
| return ObliviousHttpRequest::CreateClientObliviousRequest( |
| std::move(plaintext_data), hpke_public_key_, ohttp_key_config_); |
| } |
| |
| absl::StatusOr<ObliviousHttpResponse> |
| ObliviousHttpClient::DecryptObliviousHttpResponse( |
| std::string encrypted_data, |
| ObliviousHttpRequest::Context& oblivious_http_request_context) const { |
| return ObliviousHttpResponse::CreateClientObliviousResponse( |
| std::move(encrypted_data), oblivious_http_request_context); |
| } |
| |
| } // namespace quiche |