tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }