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