xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/oblivious_http/oblivious_http_client.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 #include "quiche/oblivious_http/oblivious_http_client.h"
2 
3 #include <stddef.h>
4 #include <stdint.h>
5 
6 #include <memory>
7 #include <string>
8 #include <utility>
9 
10 #include "absl/status/status.h"
11 #include "absl/status/statusor.h"
12 #include "absl/strings/str_cat.h"
13 #include "absl/strings/string_view.h"
14 #include "quiche/common/quiche_crypto_logging.h"
15 
16 namespace quiche {
17 
18 namespace {
19 
20 // Use BoringSSL's setup_sender API to validate whether the HPKE public key
21 // input provided by the user is valid.
ValidateClientParameters(absl::string_view hpke_public_key,const ObliviousHttpHeaderKeyConfig & ohttp_key_config)22 absl::Status ValidateClientParameters(
23     absl::string_view hpke_public_key,
24     const ObliviousHttpHeaderKeyConfig& ohttp_key_config) {
25   // Initialize HPKE client context and check if context can be setup with the
26   // given public key to verify if the public key is indeed valid.
27   bssl::UniquePtr<EVP_HPKE_CTX> client_ctx(EVP_HPKE_CTX_new());
28   if (client_ctx == nullptr) {
29     return SslErrorAsStatus(
30         "Failed to initialize HPKE ObliviousHttpClient Context.");
31   }
32   // Setup the sender (client)
33   std::string encapsulated_key(EVP_HPKE_MAX_ENC_LENGTH, '\0');
34   size_t enc_len;
35   absl::string_view info = "verify if given HPKE public key is valid";
36   if (!EVP_HPKE_CTX_setup_sender(
37           client_ctx.get(), reinterpret_cast<uint8_t*>(encapsulated_key.data()),
38           &enc_len, encapsulated_key.size(), ohttp_key_config.GetHpkeKem(),
39           ohttp_key_config.GetHpkeKdf(), ohttp_key_config.GetHpkeAead(),
40           reinterpret_cast<const uint8_t*>(hpke_public_key.data()),
41           hpke_public_key.size(), reinterpret_cast<const uint8_t*>(info.data()),
42           info.size())) {
43     return SslErrorAsStatus(
44         "Failed to setup HPKE context with given public key param "
45         "hpke_public_key.");
46   }
47   return absl::OkStatus();
48 }
49 
50 }  // namespace
51 
52 // Constructor.
ObliviousHttpClient(std::string client_public_key,const ObliviousHttpHeaderKeyConfig & ohttp_key_config)53 ObliviousHttpClient::ObliviousHttpClient(
54     std::string client_public_key,
55     const ObliviousHttpHeaderKeyConfig& ohttp_key_config)
56     : hpke_public_key_(std::move(client_public_key)),
57       ohttp_key_config_(ohttp_key_config) {}
58 
59 // Initialize Bssl.
Create(absl::string_view hpke_public_key,const ObliviousHttpHeaderKeyConfig & ohttp_key_config)60 absl::StatusOr<ObliviousHttpClient> ObliviousHttpClient::Create(
61     absl::string_view hpke_public_key,
62     const ObliviousHttpHeaderKeyConfig& ohttp_key_config) {
63   if (hpke_public_key.empty()) {
64     return absl::InvalidArgumentError("Invalid/Empty HPKE public key.");
65   }
66   auto is_valid_input =
67       ValidateClientParameters(hpke_public_key, ohttp_key_config);
68   if (!is_valid_input.ok()) {
69     return absl::InvalidArgumentError(
70         absl::StrCat("Invalid input received in method parameters. ",
71                      is_valid_input.message()));
72   }
73   return ObliviousHttpClient(std::string(hpke_public_key), ohttp_key_config);
74 }
75 
76 absl::StatusOr<ObliviousHttpRequest>
CreateObliviousHttpRequest(std::string plaintext_data) const77 ObliviousHttpClient::CreateObliviousHttpRequest(
78     std::string plaintext_data) const {
79   return ObliviousHttpRequest::CreateClientObliviousRequest(
80       std::move(plaintext_data), hpke_public_key_, ohttp_key_config_);
81 }
82 
83 absl::StatusOr<ObliviousHttpResponse>
DecryptObliviousHttpResponse(std::string encrypted_data,ObliviousHttpRequest::Context & oblivious_http_request_context) const84 ObliviousHttpClient::DecryptObliviousHttpResponse(
85     std::string encrypted_data,
86     ObliviousHttpRequest::Context& oblivious_http_request_context) const {
87   return ObliviousHttpResponse::CreateClientObliviousResponse(
88       std::move(encrypted_data), oblivious_http_request_context);
89 }
90 
91 }  // namespace quiche
92