summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/oblivious_http/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/http/oblivious_http/src/lib.rs')
-rw-r--r--netwerk/protocol/http/oblivious_http/src/lib.rs188
1 files changed, 188 insertions, 0 deletions
diff --git a/netwerk/protocol/http/oblivious_http/src/lib.rs b/netwerk/protocol/http/oblivious_http/src/lib.rs
new file mode 100644
index 0000000000..948139ab68
--- /dev/null
+++ b/netwerk/protocol/http/oblivious_http/src/lib.rs
@@ -0,0 +1,188 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+extern crate nserror;
+extern crate ohttp;
+extern crate rand;
+extern crate thin_vec;
+#[macro_use]
+extern crate xpcom;
+
+use nserror::{nsresult, NS_ERROR_FAILURE, NS_ERROR_NOT_AVAILABLE, NS_OK};
+use ohttp::hpke::{Aead, Kdf, Kem};
+use ohttp::{
+ ClientRequest, ClientResponse, KeyConfig, KeyId, Server, ServerResponse, SymmetricSuite,
+};
+use thin_vec::ThinVec;
+use xpcom::interfaces::{
+ nsIObliviousHttpClientRequest, nsIObliviousHttpClientResponse, nsIObliviousHttpServer,
+ nsIObliviousHttpServerResponse,
+};
+use xpcom::{xpcom_method, RefPtr};
+
+use std::cell::RefCell;
+
+#[xpcom(implement(nsIObliviousHttpClientResponse), atomic)]
+struct ObliviousHttpClientResponse {
+ response: RefCell<Option<ClientResponse>>,
+}
+
+impl ObliviousHttpClientResponse {
+ xpcom_method!(decapsulate => Decapsulate(enc_response: *const ThinVec<u8>) -> ThinVec<u8>);
+ fn decapsulate(&self, enc_response: &ThinVec<u8>) -> Result<ThinVec<u8>, nsresult> {
+ let response = self
+ .response
+ .borrow_mut()
+ .take()
+ .ok_or(NS_ERROR_NOT_AVAILABLE)?;
+ let decapsulated = response
+ .decapsulate(enc_response)
+ .map_err(|_| NS_ERROR_FAILURE)?;
+ Ok(decapsulated.into_iter().collect())
+ }
+}
+
+#[xpcom(implement(nsIObliviousHttpClientRequest), atomic)]
+struct ObliviousHttpClientRequest {
+ enc_request: Vec<u8>,
+ response: RefPtr<nsIObliviousHttpClientResponse>,
+}
+
+impl ObliviousHttpClientRequest {
+ xpcom_method!(get_enc_request => GetEncRequest() -> ThinVec<u8>);
+ fn get_enc_request(&self) -> Result<ThinVec<u8>, nsresult> {
+ Ok(self.enc_request.clone().into_iter().collect())
+ }
+
+ xpcom_method!(get_response => GetResponse() -> *const nsIObliviousHttpClientResponse);
+ fn get_response(&self) -> Result<RefPtr<nsIObliviousHttpClientResponse>, nsresult> {
+ Ok(self.response.clone())
+ }
+}
+
+#[xpcom(implement(nsIObliviousHttpServerResponse), atomic)]
+struct ObliviousHttpServerResponse {
+ request: Vec<u8>,
+ server_response: RefCell<Option<ServerResponse>>,
+}
+
+impl ObliviousHttpServerResponse {
+ xpcom_method!(get_request => GetRequest() -> ThinVec<u8>);
+ fn get_request(&self) -> Result<ThinVec<u8>, nsresult> {
+ Ok(self.request.clone().into_iter().collect())
+ }
+
+ xpcom_method!(encapsulate => Encapsulate(response: *const ThinVec<u8>) -> ThinVec<u8>);
+ fn encapsulate(&self, response: &ThinVec<u8>) -> Result<ThinVec<u8>, nsresult> {
+ let server_response = self
+ .server_response
+ .borrow_mut()
+ .take()
+ .ok_or(NS_ERROR_NOT_AVAILABLE)?;
+ Ok(server_response
+ .encapsulate(response)
+ .map_err(|_| NS_ERROR_FAILURE)?
+ .into_iter()
+ .collect())
+ }
+}
+
+#[xpcom(implement(nsIObliviousHttpServer), atomic)]
+struct ObliviousHttpServer {
+ server: RefCell<Server>,
+}
+
+impl ObliviousHttpServer {
+ xpcom_method!(get_encoded_config => GetEncodedConfig() -> ThinVec<u8>);
+ fn get_encoded_config(&self) -> Result<ThinVec<u8>, nsresult> {
+ let server = self.server.borrow_mut();
+ Ok(server
+ .config()
+ .encode()
+ .map_err(|_| NS_ERROR_FAILURE)?
+ .into_iter()
+ .collect())
+ }
+
+ xpcom_method!(decapsulate => Decapsulate(enc_request: *const ThinVec<u8>) -> *const nsIObliviousHttpServerResponse);
+ fn decapsulate(
+ &self,
+ enc_request: &ThinVec<u8>,
+ ) -> Result<RefPtr<nsIObliviousHttpServerResponse>, nsresult> {
+ let mut server = self.server.borrow_mut();
+ let (request, server_response) = server
+ .decapsulate(enc_request)
+ .map_err(|_| NS_ERROR_FAILURE)?;
+ let oblivious_http_server_response =
+ ObliviousHttpServerResponse::allocate(InitObliviousHttpServerResponse {
+ request,
+ server_response: RefCell::new(Some(server_response)),
+ });
+ oblivious_http_server_response
+ .query_interface::<nsIObliviousHttpServerResponse>()
+ .ok_or(NS_ERROR_FAILURE)
+ }
+}
+
+#[xpcom(implement(nsIObliviousHttp), atomic)]
+struct ObliviousHttp {}
+
+impl ObliviousHttp {
+ xpcom_method!(encapsulate_request => EncapsulateRequest(encoded_config: *const ThinVec<u8>,
+ request: *const ThinVec<u8>) -> *const nsIObliviousHttpClientRequest);
+ fn encapsulate_request(
+ &self,
+ encoded_config: &ThinVec<u8>,
+ request: &ThinVec<u8>,
+ ) -> Result<RefPtr<nsIObliviousHttpClientRequest>, nsresult> {
+ ohttp::init();
+
+ let client = ClientRequest::new(encoded_config).map_err(|_| NS_ERROR_FAILURE)?;
+ let (enc_request, response) = client.encapsulate(request).map_err(|_| NS_ERROR_FAILURE)?;
+ let oblivious_http_client_response =
+ ObliviousHttpClientResponse::allocate(InitObliviousHttpClientResponse {
+ response: RefCell::new(Some(response)),
+ });
+ let response = oblivious_http_client_response
+ .query_interface::<nsIObliviousHttpClientResponse>()
+ .ok_or(NS_ERROR_FAILURE)?;
+ let oblivious_http_client_request =
+ ObliviousHttpClientRequest::allocate(InitObliviousHttpClientRequest {
+ enc_request,
+ response,
+ });
+ oblivious_http_client_request
+ .query_interface::<nsIObliviousHttpClientRequest>()
+ .ok_or(NS_ERROR_FAILURE)
+ }
+
+ xpcom_method!(server => Server() -> *const nsIObliviousHttpServer);
+ fn server(&self) -> Result<RefPtr<nsIObliviousHttpServer>, nsresult> {
+ ohttp::init();
+
+ let key_id: KeyId = rand::random::<u8>();
+ let kem: Kem = Kem::X25519Sha256;
+ let symmetric = vec![
+ SymmetricSuite::new(Kdf::HkdfSha256, Aead::Aes128Gcm),
+ SymmetricSuite::new(Kdf::HkdfSha256, Aead::ChaCha20Poly1305),
+ ];
+ let key_config = KeyConfig::new(key_id, kem, symmetric).map_err(|_| NS_ERROR_FAILURE)?;
+ let server = Server::new(key_config).map_err(|_| NS_ERROR_FAILURE)?;
+ let oblivious_http_server = ObliviousHttpServer::allocate(InitObliviousHttpServer {
+ server: RefCell::new(server),
+ });
+ oblivious_http_server
+ .query_interface::<nsIObliviousHttpServer>()
+ .ok_or(NS_ERROR_FAILURE)
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn oblivious_http_constructor(
+ iid: *const xpcom::nsIID,
+ result: *mut *mut xpcom::reexports::libc::c_void,
+) -> nserror::nsresult {
+ let oblivious_http = ObliviousHttp::allocate(InitObliviousHttp {});
+ unsafe { oblivious_http.QueryInterface(iid, result) }
+}