1 #include <stdint.h>
2 
3 #include <string>
4 
5 #include "absl/strings/escaping.h"
6 #include "absl/strings/string_view.h"
7 #include "openssl/hpke.h"
8 #include "quiche/common/platform/api/quiche_test.h"
9 #include "quiche/oblivious_http/buffers/oblivious_http_response.h"
10 
11 namespace quiche {
12 namespace {
13 
14 struct ObliviousHttpResponseTestStrings {
15   std::string test_case_name;
16   uint8_t key_id;
17   std::string request_plaintext;
18   std::string response_plaintext;
19 };
20 
GetHpkePrivateKey()21 std::string GetHpkePrivateKey() {
22   absl::string_view hpke_key_hex =
23       "b77431ecfa8f4cfc30d6e467aafa06944dffe28cb9dd1409e33a3045f5adc8a1";
24   std::string hpke_key_bytes;
25   EXPECT_TRUE(absl::HexStringToBytes(hpke_key_hex, &hpke_key_bytes));
26   return hpke_key_bytes;
27 }
28 
GetHpkePublicKey()29 std::string GetHpkePublicKey() {
30   absl::string_view public_key =
31       "6d21cfe09fbea5122f9ebc2eb2a69fcc4f06408cd54aac934f012e76fcdcef62";
32   std::string public_key_bytes;
33   EXPECT_TRUE(absl::HexStringToBytes(public_key, &public_key_bytes));
34   return public_key_bytes;
35 }
36 
GetOhttpKeyConfig(uint8_t key_id,uint16_t kem_id,uint16_t kdf_id,uint16_t aead_id)37 const ObliviousHttpHeaderKeyConfig GetOhttpKeyConfig(uint8_t key_id,
38                                                      uint16_t kem_id,
39                                                      uint16_t kdf_id,
40                                                      uint16_t aead_id) {
41   auto ohttp_key_config =
42       ObliviousHttpHeaderKeyConfig::Create(key_id, kem_id, kdf_id, aead_id);
43   EXPECT_TRUE(ohttp_key_config.ok());
44   return std::move(ohttp_key_config.value());
45 }
46 
ConstructHpkeKey(absl::string_view hpke_key,const ObliviousHttpHeaderKeyConfig & ohttp_key_config)47 bssl::UniquePtr<EVP_HPKE_KEY> ConstructHpkeKey(
48     absl::string_view hpke_key,
49     const ObliviousHttpHeaderKeyConfig &ohttp_key_config) {
50   bssl::UniquePtr<EVP_HPKE_KEY> bssl_hpke_key(EVP_HPKE_KEY_new());
51   EXPECT_NE(bssl_hpke_key, nullptr);
52   EXPECT_TRUE(EVP_HPKE_KEY_init(
53       bssl_hpke_key.get(), ohttp_key_config.GetHpkeKem(),
54       reinterpret_cast<const uint8_t *>(hpke_key.data()), hpke_key.size()));
55   return bssl_hpke_key;
56 }
57 }  // namespace
58 
59 using ObliviousHttpParameterizedTest =
60     test::QuicheTestWithParam<ObliviousHttpResponseTestStrings>;
61 
TEST_P(ObliviousHttpParameterizedTest,TestEndToEndWithOfflineStrings)62 TEST_P(ObliviousHttpParameterizedTest, TestEndToEndWithOfflineStrings) {
63   // For each test case, verify end to end request-handling and
64   // response-handling.
65   const ObliviousHttpResponseTestStrings &test = GetParam();
66 
67   auto ohttp_key_config =
68       GetOhttpKeyConfig(test.key_id, EVP_HPKE_DHKEM_X25519_HKDF_SHA256,
69                         EVP_HPKE_HKDF_SHA256, EVP_HPKE_AES_256_GCM);
70   // Round-trip request flow.
71   auto client_req_encap = ObliviousHttpRequest::CreateClientObliviousRequest(
72       test.request_plaintext, GetHpkePublicKey(), ohttp_key_config);
73   EXPECT_TRUE(client_req_encap.ok());
74   ASSERT_FALSE(client_req_encap->EncapsulateAndSerialize().empty());
75   auto server_req_decap = ObliviousHttpRequest::CreateServerObliviousRequest(
76       client_req_encap->EncapsulateAndSerialize(),
77       *(ConstructHpkeKey(GetHpkePrivateKey(), ohttp_key_config)),
78       ohttp_key_config);
79   EXPECT_TRUE(server_req_decap.ok());
80   EXPECT_EQ(server_req_decap->GetPlaintextData(), test.request_plaintext);
81 
82   // Round-trip response flow.
83   auto server_request_context =
84       std::move(server_req_decap.value()).ReleaseContext();
85   auto server_resp_encap = ObliviousHttpResponse::CreateServerObliviousResponse(
86       test.response_plaintext, server_request_context);
87   EXPECT_TRUE(server_resp_encap.ok());
88   ASSERT_FALSE(server_resp_encap->EncapsulateAndSerialize().empty());
89   auto client_request_context =
90       std::move(client_req_encap.value()).ReleaseContext();
91   auto client_resp_decap = ObliviousHttpResponse::CreateClientObliviousResponse(
92       server_resp_encap->EncapsulateAndSerialize(), client_request_context);
93   EXPECT_TRUE(client_resp_decap.ok());
94   EXPECT_EQ(client_resp_decap->GetPlaintextData(), test.response_plaintext);
95 }
96 
97 INSTANTIATE_TEST_SUITE_P(
98     ObliviousHttpParameterizedTests, ObliviousHttpParameterizedTest,
99     testing::ValuesIn<ObliviousHttpResponseTestStrings>(
100         {{"test_case_1", 4, "test request 1", "test response 1"},
101          {"test_case_2", 6, "test request 2", "test response 2"},
102          {"test_case_3", 7, "test request 3", "test response 3"},
103          {"test_case_4", 2, "test request 4", "test response 4"},
104          {"test_case_5", 1, "test request 5", "test response 5"},
105          {"test_case_6", 7, "test request 6", "test response 6"},
106          {"test_case_7", 3, "test request 7", "test response 7"},
107          {"test_case_8", 9, "test request 8", "test response 8"},
108          {"test_case_9", 3, "test request 9", "test response 9"},
109          {"test_case_10", 4, "test request 10", "test response 10"}}),
110     [](const testing::TestParamInfo<ObliviousHttpParameterizedTest::ParamType>
__anonaabe513a0202(const testing::TestParamInfo<ObliviousHttpParameterizedTest::ParamType> &info) 111            &info) { return info.param.test_case_name; });
112 
TEST(ObliviousHttpIntegrationTest,TestWithCustomRequestResponseLabels)113 TEST(ObliviousHttpIntegrationTest, TestWithCustomRequestResponseLabels) {
114   const std::string kRequestLabel = "test_request_label";
115   const std::string kResponseLabel = "test_response_label";
116 
117   ObliviousHttpResponseTestStrings test = {"", 4, "test_request_plaintext",
118                                            "test_response_plaintext"};
119 
120   auto ohttp_key_config =
121       GetOhttpKeyConfig(test.key_id, EVP_HPKE_DHKEM_X25519_HKDF_SHA256,
122                         EVP_HPKE_HKDF_SHA256, EVP_HPKE_AES_256_GCM);
123   // Round-trip request flow.
124   auto client_req_encap = ObliviousHttpRequest::CreateClientObliviousRequest(
125       test.request_plaintext, GetHpkePublicKey(), ohttp_key_config,
126       kRequestLabel);
127   EXPECT_TRUE(client_req_encap.ok());
128   ASSERT_FALSE(client_req_encap->EncapsulateAndSerialize().empty());
129   auto server_req_decap = ObliviousHttpRequest::CreateServerObliviousRequest(
130       client_req_encap->EncapsulateAndSerialize(),
131       *(ConstructHpkeKey(GetHpkePrivateKey(), ohttp_key_config)),
132       ohttp_key_config, kRequestLabel);
133   EXPECT_TRUE(server_req_decap.ok());
134   EXPECT_EQ(server_req_decap->GetPlaintextData(), test.request_plaintext);
135 
136   auto failed_server_req_decap =
137       ObliviousHttpRequest::CreateServerObliviousRequest(
138           client_req_encap->EncapsulateAndSerialize(),
139           *(ConstructHpkeKey(GetHpkePrivateKey(), ohttp_key_config)),
140           ohttp_key_config);
141   EXPECT_FALSE(failed_server_req_decap.ok());
142 
143   // Round-trip response flow.
144   auto server_request_context =
145       std::move(server_req_decap.value()).ReleaseContext();
146   auto server_resp_encap = ObliviousHttpResponse::CreateServerObliviousResponse(
147       test.response_plaintext, server_request_context, kResponseLabel);
148   EXPECT_TRUE(server_resp_encap.ok());
149   ASSERT_FALSE(server_resp_encap->EncapsulateAndSerialize().empty());
150   auto client_request_context =
151       std::move(client_req_encap.value()).ReleaseContext();
152   auto client_resp_decap = ObliviousHttpResponse::CreateClientObliviousResponse(
153       server_resp_encap->EncapsulateAndSerialize(), client_request_context,
154       kResponseLabel);
155   EXPECT_TRUE(client_resp_decap.ok());
156   EXPECT_EQ(client_resp_decap->GetPlaintextData(), test.response_plaintext);
157 
158   auto failed_client_resp_decap =
159       ObliviousHttpResponse::CreateClientObliviousResponse(
160           server_resp_encap->EncapsulateAndSerialize(), client_request_context);
161   EXPECT_FALSE(failed_client_resp_decap.ok());
162 }
163 
164 }  // namespace quiche
165