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