1 #ifndef QUICHE_OBLIVIOUS_HTTP_BUFFERS_OBLIVIOUS_HTTP_REQUEST_H_
2 #define QUICHE_OBLIVIOUS_HTTP_BUFFERS_OBLIVIOUS_HTTP_REQUEST_H_
3 
4 #include <memory>
5 #include <optional>
6 #include <string>
7 
8 #include "absl/status/statusor.h"
9 #include "absl/strings/string_view.h"
10 #include "openssl/hpke.h"
11 #include "quiche/oblivious_http/common/oblivious_http_header_key_config.h"
12 
13 namespace quiche {
14 // 1. Handles client side encryption of the payload that will subsequently be
15 // added to HTTP POST body and passed on to Relay.
16 // 2. Handles server side decryption of the payload received in HTTP POST body
17 // from Relay.
18 // https://www.ietf.org/archive/id/draft-ietf-ohai-ohttp-03.html#name-encapsulation-of-requests
19 class QUICHE_EXPORT ObliviousHttpRequest {
20  public:
21   // Holds the HPKE related data received from request. This context is created
22   // during request processing, and subsequently passed into response handling
23   // in `ObliviousHttpResponse`.
24   class QUICHE_EXPORT Context {
25    public:
26     ~Context() = default;
27 
28     // Movable
29     Context(Context&& other) = default;
30     Context& operator=(Context&& other) = default;
31 
32    private:
33     explicit Context(bssl::UniquePtr<EVP_HPKE_CTX> hpke_context,
34                      std::string encapsulated_key);
35 
36     // All accessors must be friends to read `Context`.
37     friend class ObliviousHttpRequest;
38     friend class ObliviousHttpResponse;
39     // Tests which need access.
40     friend class
41         ObliviousHttpRequest_TestDecapsulateWithSpecAppendixAExample_Test;
42     friend class ObliviousHttpRequest_TestEncapsulatedRequestStructure_Test;
43     friend class
44         ObliviousHttpRequest_TestEncapsulatedOhttpEncryptedPayload_Test;
45     friend class ObliviousHttpRequest_TestDeterministicSeededOhttpRequest_Test;
46     friend class ObliviousHttpResponse_EndToEndTestForResponse_Test;
47     friend class ObliviousHttpResponse_TestEncapsulateWithQuicheRandom_Test;
48 
49     bssl::UniquePtr<EVP_HPKE_CTX> hpke_context_;
50     std::string encapsulated_key_;
51   };
52   // Parse the OHTTP request from the given `encrypted_data`.
53   // On success, returns obj that callers will use to `GetPlaintextData`.
54   // Generic Usecase : server-side calls this method in the context of Request.
55   static absl::StatusOr<ObliviousHttpRequest> CreateServerObliviousRequest(
56       absl::string_view encrypted_data, const EVP_HPKE_KEY& gateway_key,
57       const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
58       absl::string_view request_label =
59           ObliviousHttpHeaderKeyConfig::kOhttpRequestLabel);
60 
61   // Constructs an OHTTP request for the given `plaintext_payload`.
62   // On success, returns obj that callers will use to `EncapsulateAndSerialize`
63   // OHttp request.
64   static absl::StatusOr<ObliviousHttpRequest> CreateClientObliviousRequest(
65       std::string plaintext_payload, absl::string_view hpke_public_key,
66       const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
67       absl::string_view request_label =
68           ObliviousHttpHeaderKeyConfig::kOhttpRequestLabel);
69 
70   // Same as above but accepts a random number seed for testing.
71   static absl::StatusOr<ObliviousHttpRequest> CreateClientWithSeedForTesting(
72       std::string plaintext_payload, absl::string_view hpke_public_key,
73       const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
74       absl::string_view seed,
75       absl::string_view request_label =
76           ObliviousHttpHeaderKeyConfig::kOhttpRequestLabel);
77 
78   // Movable.
79   ObliviousHttpRequest(ObliviousHttpRequest&& other) = default;
80   ObliviousHttpRequest& operator=(ObliviousHttpRequest&& other) = default;
81 
82   ~ObliviousHttpRequest() = default;
83 
84   // Returns serialized OHTTP request bytestring.
85   // @note: This method MUST NOT be called after `ReleaseContext()` has been
86   // called.
87   std::string EncapsulateAndSerialize() const;
88 
89   // Generic Usecase : server-side calls this method after Decapsulation using
90   // `CreateServerObliviousRequest`.
91   absl::string_view GetPlaintextData() const;
92 
93   // Oblivious HTTP request context is created after successful creation of
94   // `this` object, and subsequently passed into the `ObliviousHttpResponse` for
95   // followup response handling.
96   // @returns: This rvalue reference qualified member function transfers the
97   // ownership of `Context` to the caller, and further invokes
98   // ClangTidy:misc-use-after-move warning if callers try to extract `Context`
99   // twice after the fact that the ownership has already been transferred.
100   // @note: Callers shouldn't extract the `Context` until you're done with this
101   // Request and its data.
ReleaseContext()102   Context ReleaseContext() && {
103     return std::move(oblivious_http_request_context_.value());
104   }
105 
106  private:
107   explicit ObliviousHttpRequest(
108       bssl::UniquePtr<EVP_HPKE_CTX> hpke_context, std::string encapsulated_key,
109       const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
110       std::string req_ciphertext, std::string req_plaintext);
111 
112   static absl::StatusOr<ObliviousHttpRequest> EncapsulateWithSeed(
113       std::string plaintext_payload, absl::string_view hpke_public_key,
114       const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
115       absl::string_view seed, absl::string_view request_label);
116 
117   // This field will be empty after calling `ReleaseContext()`.
118   std::optional<Context> oblivious_http_request_context_;
119   ObliviousHttpHeaderKeyConfig key_config_;
120   std::string request_ciphertext_;
121   std::string request_plaintext_;
122 };
123 
124 }  // namespace quiche
125 
126 #endif  // QUICHE_OBLIVIOUS_HTTP_BUFFERS_OBLIVIOUS_HTTP_REQUEST_H_
127