1 #include "quiche/oblivious_http/buffers/oblivious_http_response.h"
2 
3 #include <stddef.h>
4 #include <stdint.h>
5 #include <string.h>
6 
7 #include <memory>
8 #include <string>
9 #include <utility>
10 
11 #include "absl/status/statusor.h"
12 #include "absl/strings/escaping.h"
13 #include "absl/strings/str_cat.h"
14 #include "absl/strings/string_view.h"
15 #include "openssl/hpke.h"
16 #include "quiche/common/platform/api/quiche_test.h"
17 #include "quiche/oblivious_http/buffers/oblivious_http_request.h"
18 #include "quiche/oblivious_http/common/oblivious_http_header_key_config.h"
19 
20 namespace quiche {
21 
22 namespace {
GetHpkePrivateKey()23 std::string GetHpkePrivateKey() {
24   absl::string_view hpke_key_hex =
25       "b77431ecfa8f4cfc30d6e467aafa06944dffe28cb9dd1409e33a3045f5adc8a1";
26   std::string hpke_key_bytes;
27   EXPECT_TRUE(absl::HexStringToBytes(hpke_key_hex, &hpke_key_bytes));
28   return hpke_key_bytes;
29 }
30 
GetHpkePublicKey()31 std::string GetHpkePublicKey() {
32   absl::string_view public_key =
33       "6d21cfe09fbea5122f9ebc2eb2a69fcc4f06408cd54aac934f012e76fcdcef62";
34   std::string public_key_bytes;
35   EXPECT_TRUE(absl::HexStringToBytes(public_key, &public_key_bytes));
36   return public_key_bytes;
37 }
38 
GetSeed()39 std::string GetSeed() {
40   absl::string_view seed =
41       "52c4a758a802cd8b936eceea314432798d5baf2d7e9235dc084ab1b9cfa2f736";
42   std::string seed_bytes;
43   EXPECT_TRUE(absl::HexStringToBytes(seed, &seed_bytes));
44   return seed_bytes;
45 }
46 
GetSeededEncapsulatedKey()47 std::string GetSeededEncapsulatedKey() {
48   absl::string_view encapsulated_key =
49       "37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431";
50   std::string encapsulated_key_bytes;
51   EXPECT_TRUE(
52       absl::HexStringToBytes(encapsulated_key, &encapsulated_key_bytes));
53   return encapsulated_key_bytes;
54 }
55 
GetOhttpKeyConfig(uint8_t key_id,uint16_t kem_id,uint16_t kdf_id,uint16_t aead_id)56 const ObliviousHttpHeaderKeyConfig GetOhttpKeyConfig(uint8_t key_id,
57                                                      uint16_t kem_id,
58                                                      uint16_t kdf_id,
59                                                      uint16_t aead_id) {
60   auto ohttp_key_config =
61       ObliviousHttpHeaderKeyConfig::Create(key_id, kem_id, kdf_id, aead_id);
62   EXPECT_TRUE(ohttp_key_config.ok());
63   return ohttp_key_config.value();
64 }
65 
GetSeededClientContext(uint8_t key_id,uint16_t kem_id,uint16_t kdf_id,uint16_t aead_id)66 bssl::UniquePtr<EVP_HPKE_CTX> GetSeededClientContext(uint8_t key_id,
67                                                      uint16_t kem_id,
68                                                      uint16_t kdf_id,
69                                                      uint16_t aead_id) {
70   bssl::UniquePtr<EVP_HPKE_CTX> client_ctx(EVP_HPKE_CTX_new());
71   std::string encapsulated_key(EVP_HPKE_MAX_ENC_LENGTH, '\0');
72   size_t enc_len;
73   std::string info = GetOhttpKeyConfig(key_id, kem_id, kdf_id, aead_id)
74                          .SerializeRecipientContextInfo();
75 
76   EXPECT_TRUE(EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
77       client_ctx.get(), reinterpret_cast<uint8_t *>(encapsulated_key.data()),
78       &enc_len, encapsulated_key.size(), EVP_hpke_x25519_hkdf_sha256(),
79       EVP_hpke_hkdf_sha256(), EVP_hpke_aes_256_gcm(),
80       reinterpret_cast<const uint8_t *>(GetHpkePublicKey().data()),
81       GetHpkePublicKey().size(), reinterpret_cast<const uint8_t *>(info.data()),
82       info.size(), reinterpret_cast<const uint8_t *>(GetSeed().data()),
83       GetSeed().size()));
84   encapsulated_key.resize(enc_len);
85   EXPECT_EQ(encapsulated_key, GetSeededEncapsulatedKey());
86   return client_ctx;
87 }
88 
ConstructHpkeKey(absl::string_view hpke_key,const ObliviousHttpHeaderKeyConfig & ohttp_key_config)89 bssl::UniquePtr<EVP_HPKE_KEY> ConstructHpkeKey(
90     absl::string_view hpke_key,
91     const ObliviousHttpHeaderKeyConfig &ohttp_key_config) {
92   bssl::UniquePtr<EVP_HPKE_KEY> bssl_hpke_key(EVP_HPKE_KEY_new());
93   EXPECT_NE(bssl_hpke_key, nullptr);
94   EXPECT_TRUE(EVP_HPKE_KEY_init(
95       bssl_hpke_key.get(), ohttp_key_config.GetHpkeKem(),
96       reinterpret_cast<const uint8_t *>(hpke_key.data()), hpke_key.size()));
97   return bssl_hpke_key;
98 }
99 
SetUpObliviousHttpContext(uint8_t key_id,uint16_t kem_id,uint16_t kdf_id,uint16_t aead_id,std::string plaintext)100 ObliviousHttpRequest SetUpObliviousHttpContext(uint8_t key_id, uint16_t kem_id,
101                                                uint16_t kdf_id,
102                                                uint16_t aead_id,
103                                                std::string plaintext) {
104   auto ohttp_key_config = GetOhttpKeyConfig(key_id, kem_id, kdf_id, aead_id);
105   auto client_request_encapsulate =
106       ObliviousHttpRequest::CreateClientWithSeedForTesting(
107           std::move(plaintext), GetHpkePublicKey(), ohttp_key_config,
108           GetSeed());
109   EXPECT_TRUE(client_request_encapsulate.ok());
110   auto oblivious_request =
111       client_request_encapsulate->EncapsulateAndSerialize();
112   auto server_request_decapsulate =
113       ObliviousHttpRequest::CreateServerObliviousRequest(
114           oblivious_request,
115           *(ConstructHpkeKey(GetHpkePrivateKey(), ohttp_key_config)),
116           ohttp_key_config);
117   EXPECT_TRUE(server_request_decapsulate.ok());
118   return std::move(server_request_decapsulate.value());
119 }
120 
121 // QuicheRandom implementation.
122 // Just fills the buffer with repeated chars that's initialized in seed.
123 class TestQuicheRandom : public QuicheRandom {
124  public:
TestQuicheRandom(char seed)125   TestQuicheRandom(char seed) : seed_(seed) {}
~TestQuicheRandom()126   ~TestQuicheRandom() override {}
127 
RandBytes(void * data,size_t len)128   void RandBytes(void *data, size_t len) override { memset(data, seed_, len); }
129 
RandUint64()130   uint64_t RandUint64() override {
131     uint64_t random_int;
132     memset(&random_int, seed_, sizeof(random_int));
133     return random_int;
134   }
135 
InsecureRandBytes(void * data,size_t len)136   void InsecureRandBytes(void *data, size_t len) override {
137     return RandBytes(data, len);
138   }
InsecureRandUint64()139   uint64_t InsecureRandUint64() override { return RandUint64(); }
140 
141  private:
142   char seed_;
143 };
144 
GetResponseNonceLength(const EVP_HPKE_CTX & hpke_context)145 size_t GetResponseNonceLength(const EVP_HPKE_CTX &hpke_context) {
146   EXPECT_NE(&hpke_context, nullptr);
147   const EVP_AEAD *evp_hpke_aead =
148       EVP_HPKE_AEAD_aead(EVP_HPKE_CTX_aead(&hpke_context));
149   EXPECT_NE(evp_hpke_aead, nullptr);
150   // Nk = [AEAD key len], is determined by BSSL.
151   const size_t aead_key_len = EVP_AEAD_key_length(evp_hpke_aead);
152   // Nn = [AEAD nonce len], is determined by BSSL.
153   const size_t aead_nonce_len = EVP_AEAD_nonce_length(evp_hpke_aead);
154   const size_t secret_len = std::max(aead_key_len, aead_nonce_len);
155   return secret_len;
156 }
157 
TEST(ObliviousHttpResponse,TestDecapsulateReceivedResponse)158 TEST(ObliviousHttpResponse, TestDecapsulateReceivedResponse) {
159   // Construct encrypted payload with plaintext: "test response"
160   absl::string_view encrypted_response =
161       "39d5b03c02c97e216df444e4681007105974d4df1585aae05e7b53f3ccdb55d51f711d48"
162       "eeefbc1a555d6d928e35df33fd23c23846fa7b083e30692f7b";
163   std::string encrypted_response_bytes;
164   ASSERT_TRUE(
165       absl::HexStringToBytes(encrypted_response, &encrypted_response_bytes));
166   auto oblivious_context =
167       SetUpObliviousHttpContext(4, EVP_HPKE_DHKEM_X25519_HKDF_SHA256,
168                                 EVP_HPKE_HKDF_SHA256, EVP_HPKE_AES_256_GCM,
169                                 "test")
170           .ReleaseContext();
171   auto decapsulated = ObliviousHttpResponse::CreateClientObliviousResponse(
172       std::move(encrypted_response_bytes), oblivious_context);
173   EXPECT_TRUE(decapsulated.ok());
174   auto decrypted = decapsulated->GetPlaintextData();
175   EXPECT_EQ(decrypted, "test response");
176 }
177 }  // namespace
178 
TEST(ObliviousHttpResponse,EndToEndTestForResponse)179 TEST(ObliviousHttpResponse, EndToEndTestForResponse) {
180   auto oblivious_ctx = ObliviousHttpRequest::Context(
181       GetSeededClientContext(5, EVP_HPKE_DHKEM_X25519_HKDF_SHA256,
182                              EVP_HPKE_HKDF_SHA256, EVP_HPKE_AES_256_GCM),
183       GetSeededEncapsulatedKey());
184   auto server_response_encapsulate =
185       ObliviousHttpResponse::CreateServerObliviousResponse("test response",
186                                                            oblivious_ctx);
187   EXPECT_TRUE(server_response_encapsulate.ok());
188   auto oblivious_response =
189       server_response_encapsulate->EncapsulateAndSerialize();
190   auto client_response_encapsulate =
191       ObliviousHttpResponse::CreateClientObliviousResponse(oblivious_response,
192                                                            oblivious_ctx);
193   auto decrypted = client_response_encapsulate->GetPlaintextData();
194   EXPECT_EQ(decrypted, "test response");
195 }
196 
TEST(ObliviousHttpResponse,TestEncapsulateWithQuicheRandom)197 TEST(ObliviousHttpResponse, TestEncapsulateWithQuicheRandom) {
198   auto random = TestQuicheRandom('z');
199   auto server_seeded_request = SetUpObliviousHttpContext(
200       6, EVP_HPKE_DHKEM_X25519_HKDF_SHA256, EVP_HPKE_HKDF_SHA256,
201       EVP_HPKE_AES_256_GCM, "test");
202   auto server_request_context =
203       std::move(server_seeded_request).ReleaseContext();
204   auto server_response_encapsulate =
205       ObliviousHttpResponse::CreateServerObliviousResponse(
206           "test response", server_request_context,
207           ObliviousHttpHeaderKeyConfig::kOhttpResponseLabel, &random);
208   EXPECT_TRUE(server_response_encapsulate.ok());
209   std::string response_nonce =
210       server_response_encapsulate->EncapsulateAndSerialize().substr(
211           0, GetResponseNonceLength(*(server_request_context.hpke_context_)));
212   EXPECT_EQ(response_nonce,
213             std::string(
214                 GetResponseNonceLength(*(server_request_context.hpke_context_)),
215                 'z'));
216   absl::string_view expected_encrypted_response =
217       "2a3271ac4e6a501f51d0264d3dd7d0bc8a06973b58e89c26d6dac06144";
218   std::string expected_encrypted_response_bytes;
219   ASSERT_TRUE(absl::HexStringToBytes(expected_encrypted_response,
220                                      &expected_encrypted_response_bytes));
221   EXPECT_EQ(
222       server_response_encapsulate->EncapsulateAndSerialize().substr(
223           GetResponseNonceLength(*(server_request_context.hpke_context_))),
224       expected_encrypted_response_bytes);
225 }
226 
227 }  // namespace quiche
228