lib.rs (7422B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 extern crate nserror; 6 extern crate ohttp; 7 extern crate rand; 8 extern crate thin_vec; 9 #[macro_use] 10 extern crate xpcom; 11 12 use nserror::{nsresult, NS_ERROR_FAILURE, NS_ERROR_NOT_AVAILABLE, NS_OK}; 13 use ohttp::hpke::{Aead, Kdf, Kem}; 14 use ohttp::{ 15 ClientRequest, ClientResponse, KeyConfig, KeyId, Server, ServerResponse, SymmetricSuite, 16 }; 17 use thin_vec::ThinVec; 18 use xpcom::interfaces::{ 19 nsIObliviousHttpClientRequest, nsIObliviousHttpClientResponse, nsIObliviousHttpServer, 20 nsIObliviousHttpServerResponse, 21 }; 22 use xpcom::{xpcom_method, RefPtr}; 23 24 use std::cell::RefCell; 25 26 #[xpcom(implement(nsIObliviousHttpClientResponse), atomic)] 27 struct ObliviousHttpClientResponse { 28 response: RefCell<Option<ClientResponse>>, 29 } 30 31 impl ObliviousHttpClientResponse { 32 xpcom_method!(decapsulate => Decapsulate(enc_response: *const ThinVec<u8>) -> ThinVec<u8>); 33 fn decapsulate(&self, enc_response: &ThinVec<u8>) -> Result<ThinVec<u8>, nsresult> { 34 let response = self 35 .response 36 .borrow_mut() 37 .take() 38 .ok_or(NS_ERROR_NOT_AVAILABLE)?; 39 let decapsulated = response 40 .decapsulate(enc_response) 41 .map_err(|_| NS_ERROR_FAILURE)?; 42 Ok(decapsulated.into_iter().collect()) 43 } 44 } 45 46 #[xpcom(implement(nsIObliviousHttpClientRequest), atomic)] 47 struct ObliviousHttpClientRequest { 48 enc_request: Vec<u8>, 49 response: RefPtr<nsIObliviousHttpClientResponse>, 50 } 51 52 impl ObliviousHttpClientRequest { 53 xpcom_method!(get_enc_request => GetEncRequest() -> ThinVec<u8>); 54 fn get_enc_request(&self) -> Result<ThinVec<u8>, nsresult> { 55 Ok(self.enc_request.clone().into_iter().collect()) 56 } 57 58 xpcom_method!(get_response => GetResponse() -> *const nsIObliviousHttpClientResponse); 59 fn get_response(&self) -> Result<RefPtr<nsIObliviousHttpClientResponse>, nsresult> { 60 Ok(self.response.clone()) 61 } 62 } 63 64 #[xpcom(implement(nsIObliviousHttpServerResponse), atomic)] 65 struct ObliviousHttpServerResponse { 66 request: Vec<u8>, 67 server_response: RefCell<Option<ServerResponse>>, 68 } 69 70 impl ObliviousHttpServerResponse { 71 xpcom_method!(get_request => GetRequest() -> ThinVec<u8>); 72 fn get_request(&self) -> Result<ThinVec<u8>, nsresult> { 73 Ok(self.request.clone().into_iter().collect()) 74 } 75 76 xpcom_method!(encapsulate => Encapsulate(response: *const ThinVec<u8>) -> ThinVec<u8>); 77 fn encapsulate(&self, response: &ThinVec<u8>) -> Result<ThinVec<u8>, nsresult> { 78 let server_response = self 79 .server_response 80 .borrow_mut() 81 .take() 82 .ok_or(NS_ERROR_NOT_AVAILABLE)?; 83 Ok(server_response 84 .encapsulate(response) 85 .map_err(|_| NS_ERROR_FAILURE)? 86 .into_iter() 87 .collect()) 88 } 89 } 90 91 #[xpcom(implement(nsIObliviousHttpServer), atomic)] 92 struct ObliviousHttpServer { 93 server: RefCell<Server>, 94 } 95 96 impl ObliviousHttpServer { 97 xpcom_method!(get_encoded_config => GetEncodedConfig() -> ThinVec<u8>); 98 fn get_encoded_config(&self) -> Result<ThinVec<u8>, nsresult> { 99 let server = self.server.borrow_mut(); 100 Ok(server 101 .config() 102 .encode() 103 .map_err(|_| NS_ERROR_FAILURE)? 104 .into_iter() 105 .collect()) 106 } 107 108 xpcom_method!(decapsulate => Decapsulate(enc_request: *const ThinVec<u8>) -> *const nsIObliviousHttpServerResponse); 109 fn decapsulate( 110 &self, 111 enc_request: &ThinVec<u8>, 112 ) -> Result<RefPtr<nsIObliviousHttpServerResponse>, nsresult> { 113 let server = self.server.borrow_mut(); 114 let (request, server_response) = server 115 .decapsulate(enc_request) 116 .map_err(|_| NS_ERROR_FAILURE)?; 117 let oblivious_http_server_response = 118 ObliviousHttpServerResponse::allocate(InitObliviousHttpServerResponse { 119 request, 120 server_response: RefCell::new(Some(server_response)), 121 }); 122 oblivious_http_server_response 123 .query_interface::<nsIObliviousHttpServerResponse>() 124 .ok_or(NS_ERROR_FAILURE) 125 } 126 } 127 128 #[xpcom(implement(nsIObliviousHttp), atomic)] 129 struct ObliviousHttp {} 130 131 impl ObliviousHttp { 132 xpcom_method!(encapsulate_request => EncapsulateRequest(encoded_config: *const ThinVec<u8>, 133 request: *const ThinVec<u8>) -> *const nsIObliviousHttpClientRequest); 134 fn encapsulate_request( 135 &self, 136 encoded_config: &ThinVec<u8>, 137 request: &ThinVec<u8>, 138 ) -> Result<RefPtr<nsIObliviousHttpClientRequest>, nsresult> { 139 ohttp::init(); 140 141 let client = 142 ClientRequest::from_encoded_config(encoded_config).map_err(|_| NS_ERROR_FAILURE)?; 143 let (enc_request, response) = client.encapsulate(request).map_err(|_| NS_ERROR_FAILURE)?; 144 let oblivious_http_client_response = 145 ObliviousHttpClientResponse::allocate(InitObliviousHttpClientResponse { 146 response: RefCell::new(Some(response)), 147 }); 148 let response = oblivious_http_client_response 149 .query_interface::<nsIObliviousHttpClientResponse>() 150 .ok_or(NS_ERROR_FAILURE)?; 151 let oblivious_http_client_request = 152 ObliviousHttpClientRequest::allocate(InitObliviousHttpClientRequest { 153 enc_request, 154 response, 155 }); 156 oblivious_http_client_request 157 .query_interface::<nsIObliviousHttpClientRequest>() 158 .ok_or(NS_ERROR_FAILURE) 159 } 160 161 xpcom_method!(server => Server() -> *const nsIObliviousHttpServer); 162 fn server(&self) -> Result<RefPtr<nsIObliviousHttpServer>, nsresult> { 163 ohttp::init(); 164 165 let key_id: KeyId = rand::random::<u8>(); 166 let kem: Kem = Kem::X25519Sha256; 167 let symmetric = vec![ 168 SymmetricSuite::new(Kdf::HkdfSha256, Aead::Aes128Gcm), 169 SymmetricSuite::new(Kdf::HkdfSha256, Aead::ChaCha20Poly1305), 170 ]; 171 let key_config = KeyConfig::new(key_id, kem, symmetric).map_err(|_| NS_ERROR_FAILURE)?; 172 let server = Server::new(key_config).map_err(|_| NS_ERROR_FAILURE)?; 173 let oblivious_http_server = ObliviousHttpServer::allocate(InitObliviousHttpServer { 174 server: RefCell::new(server), 175 }); 176 oblivious_http_server 177 .query_interface::<nsIObliviousHttpServer>() 178 .ok_or(NS_ERROR_FAILURE) 179 } 180 181 xpcom_method!(decode_config_list => DecodeConfigList(encoded_config_list: *const ThinVec<u8>) -> ThinVec<ThinVec<u8>>); 182 fn decode_config_list( 183 &self, 184 encoded_config_list: &ThinVec<u8>, 185 ) -> Result<ThinVec<ThinVec<u8>>, nsresult> { 186 let configs = KeyConfig::decode_list(encoded_config_list) 187 .map_err(|_| NS_ERROR_FAILURE)? 188 .into_iter() 189 .map(|config| config.encode().unwrap()) 190 .map(ThinVec::from) 191 .collect(); 192 Ok(configs) 193 } 194 } 195 196 #[no_mangle] 197 pub extern "C" fn oblivious_http_constructor( 198 iid: *const xpcom::nsIID, 199 result: *mut *mut xpcom::reexports::libc::c_void, 200 ) -> nserror::nsresult { 201 let oblivious_http = ObliviousHttp::allocate(InitObliviousHttp {}); 202 unsafe { oblivious_http.QueryInterface(iid, result) } 203 }