blob: 8a77c752e0da0903f5c62c68c03611f764336182 [file] [log] [blame] [edit]
#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