test work
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								veilid-core/0qrl21wlR1IjCA13sIOjw7Byk8ruCfPcnVBRxMLHCrk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								veilid-core/0qrl21wlR1IjCA13sIOjw7Byk8ruCfPcnVBRxMLHCrk
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								veilid-core/BrpdAUI1bcti0_vJinSu42N9w-vNQRfWBGaR8DLGnAY
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								veilid-core/BrpdAUI1bcti0_vJinSu42N9w-vNQRfWBGaR8DLGnAY
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								veilid-core/bazGk6a59NnYJyQ-s5bQu3GogeYnRpkHJss5vba1khA
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								veilid-core/bazGk6a59NnYJyQ-s5bQu3GogeYnRpkHJss5vba1khA
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -5,11 +5,7 @@ fn fake_routing_table() -> routing_table::RoutingTable {
 | 
			
		||||
    let block_store = BlockStore::new(veilid_config.clone());
 | 
			
		||||
    let protected_store = ProtectedStore::new(veilid_config.clone());
 | 
			
		||||
    let table_store = TableStore::new(veilid_config.clone(), protected_store.clone());
 | 
			
		||||
    let crypto = Crypto::new(
 | 
			
		||||
        veilid_config.clone(),
 | 
			
		||||
        table_store.clone(),
 | 
			
		||||
        protected_store.clone(),
 | 
			
		||||
    );
 | 
			
		||||
    let crypto = Crypto::new(veilid_config.clone(), table_store.clone());
 | 
			
		||||
    let storage_manager = storage_manager::StorageManager::new(
 | 
			
		||||
        veilid_config.clone(),
 | 
			
		||||
        crypto.clone(),
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,8 @@ mod table_store;
 | 
			
		||||
pub use table_db::*;
 | 
			
		||||
pub use table_store::*;
 | 
			
		||||
 | 
			
		||||
pub mod tests;
 | 
			
		||||
 | 
			
		||||
#[cfg(target_arch = "wasm32")]
 | 
			
		||||
mod wasm;
 | 
			
		||||
#[cfg(target_arch = "wasm32")]
 | 
			
		||||
 
 | 
			
		||||
@@ -163,15 +163,11 @@ impl TableStore {
 | 
			
		||||
        self.flush().await;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn load_device_encryption_key(&self) -> EyreResult<Option<TypedSharedSecret>> {
 | 
			
		||||
        let dek_bytes: Option<Vec<u8>> = self
 | 
			
		||||
            .protected_store
 | 
			
		||||
            .load_user_secret("device_encryption_key")
 | 
			
		||||
            .await?;
 | 
			
		||||
        let Some(dek_bytes) = dek_bytes else {
 | 
			
		||||
            return Ok(None);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    pub fn maybe_unprotect_device_encryption_key(
 | 
			
		||||
        &self,
 | 
			
		||||
        dek_bytes: &[u8],
 | 
			
		||||
        device_encryption_key_password: &str,
 | 
			
		||||
    ) -> EyreResult<TypedSharedSecret> {
 | 
			
		||||
        // Ensure the key is at least as long as necessary if unencrypted
 | 
			
		||||
        if dek_bytes.len() < (4 + SHARED_SECRET_LENGTH) {
 | 
			
		||||
            bail!("device encryption key is not valid");
 | 
			
		||||
@@ -184,11 +180,6 @@ impl TableStore {
 | 
			
		||||
            bail!("unsupported cryptosystem");
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Decrypt encryption key if we have it
 | 
			
		||||
        let device_encryption_key_password = {
 | 
			
		||||
            let c = self.config.get();
 | 
			
		||||
            c.protected_store.device_encryption_key_password.clone()
 | 
			
		||||
        };
 | 
			
		||||
        if !device_encryption_key_password.is_empty() {
 | 
			
		||||
            if dek_bytes.len()
 | 
			
		||||
                != (4 + SHARED_SECRET_LENGTH + vcrypto.aead_overhead() + NONCE_LENGTH)
 | 
			
		||||
@@ -209,28 +200,126 @@ impl TableStore {
 | 
			
		||||
                    None,
 | 
			
		||||
                )
 | 
			
		||||
                .wrap_err("failed to decrypt device encryption key")?;
 | 
			
		||||
            return Ok(Some(TypedSharedSecret::new(
 | 
			
		||||
            return Ok(TypedSharedSecret::new(
 | 
			
		||||
                kind,
 | 
			
		||||
                SharedSecret::try_from(unprotected_key.as_slice())
 | 
			
		||||
                    .wrap_err("invalid shared secret")?,
 | 
			
		||||
            )));
 | 
			
		||||
            ));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(Some(TypedSharedSecret::new(
 | 
			
		||||
        Ok(TypedSharedSecret::new(
 | 
			
		||||
            kind,
 | 
			
		||||
            SharedSecret::try_from(&dek_bytes[4..])?,
 | 
			
		||||
        )))
 | 
			
		||||
        ))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn maybe_protect_device_encryption_key(
 | 
			
		||||
        &self,
 | 
			
		||||
        dek: TypedSharedSecret,
 | 
			
		||||
        device_encryption_key_password: &str,
 | 
			
		||||
    ) -> EyreResult<Vec<u8>> {
 | 
			
		||||
        // Check if we are to protect the key
 | 
			
		||||
        if device_encryption_key_password.is_empty() {
 | 
			
		||||
            // Return the unprotected key bytes
 | 
			
		||||
            let mut out = Vec::with_capacity(4 + SHARED_SECRET_LENGTH);
 | 
			
		||||
            out.extend_from_slice(&dek.kind.0);
 | 
			
		||||
            out.extend_from_slice(&dek.value.bytes);
 | 
			
		||||
            return Ok(out);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get cryptosystem
 | 
			
		||||
        let crypto = self.inner.lock().crypto.as_ref().unwrap().clone();
 | 
			
		||||
        let Some(vcrypto) = crypto.get(dek.kind) else {
 | 
			
		||||
            bail!("unsupported cryptosystem");
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let nonce = vcrypto.random_nonce();
 | 
			
		||||
        let shared_secret = vcrypto
 | 
			
		||||
            .derive_shared_secret(device_encryption_key_password.as_bytes(), &nonce.bytes)
 | 
			
		||||
            .wrap_err("failed to derive shared secret")?;
 | 
			
		||||
        let mut protected_key = vcrypto
 | 
			
		||||
            .encrypt_aead(
 | 
			
		||||
                &dek.value.bytes,
 | 
			
		||||
                &Nonce::try_from(nonce).wrap_err("invalid nonce")?,
 | 
			
		||||
                &shared_secret,
 | 
			
		||||
                None,
 | 
			
		||||
            )
 | 
			
		||||
            .wrap_err("failed to decrypt device encryption key")?;
 | 
			
		||||
        let mut out =
 | 
			
		||||
            Vec::with_capacity(4 + SHARED_SECRET_LENGTH + vcrypto.aead_overhead() + NONCE_LENGTH);
 | 
			
		||||
        out.extend_from_slice(&dek.kind.0);
 | 
			
		||||
        out.append(&mut protected_key);
 | 
			
		||||
        out.extend_from_slice(&nonce.bytes);
 | 
			
		||||
        assert!(out.len() == 4 + SHARED_SECRET_LENGTH + vcrypto.aead_overhead() + NONCE_LENGTH);
 | 
			
		||||
        Ok(out)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async fn load_device_encryption_key(&self) -> EyreResult<Option<TypedSharedSecret>> {
 | 
			
		||||
        let dek_bytes: Option<Vec<u8>> = self
 | 
			
		||||
            .protected_store
 | 
			
		||||
            .load_user_secret("device_encryption_key")
 | 
			
		||||
            .await?;
 | 
			
		||||
        let Some(dek_bytes) = dek_bytes else {
 | 
			
		||||
            return Ok(None);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Get device encryption key protection password if we have it
 | 
			
		||||
        let device_encryption_key_password = {
 | 
			
		||||
            let c = self.config.get();
 | 
			
		||||
            c.protected_store.device_encryption_key_password.clone()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Ok(Some(self.maybe_unprotect_device_encryption_key(
 | 
			
		||||
            &dek_bytes,
 | 
			
		||||
            &device_encryption_key_password,
 | 
			
		||||
        )?))
 | 
			
		||||
    }
 | 
			
		||||
    async fn save_device_encryption_key(
 | 
			
		||||
        &self,
 | 
			
		||||
        device_encryption_key: Option<TypedSharedSecret>,
 | 
			
		||||
    ) -> EyreResult<()> {
 | 
			
		||||
        // Save the new device encryption key
 | 
			
		||||
        self.protected_store
 | 
			
		||||
            .save_user_secret_json("device_encryption_key", &device_encryption_key)
 | 
			
		||||
            .await?;
 | 
			
		||||
        let Some(device_encryption_key) = device_encryption_key else {
 | 
			
		||||
            // Remove the device encryption key
 | 
			
		||||
            let existed = self
 | 
			
		||||
                .protected_store
 | 
			
		||||
                .remove_user_secret("device_encryption_key")
 | 
			
		||||
                .await?;
 | 
			
		||||
            trace!("removed device encryption key. existed: {}", existed);
 | 
			
		||||
            return Ok(());
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
xxxx
 | 
			
		||||
        // Get new device encryption key protection password if we are changing it
 | 
			
		||||
        let new_device_encryption_key_password = {
 | 
			
		||||
            let c = self.config.get();
 | 
			
		||||
            c.protected_store.new_device_encryption_key_password.clone()
 | 
			
		||||
        };
 | 
			
		||||
        let device_encryption_key_password =
 | 
			
		||||
            if let Some(new_device_encryption_key_password) = new_device_encryption_key_password {
 | 
			
		||||
                // Change password
 | 
			
		||||
                self.config
 | 
			
		||||
                    .with_mut(|c| {
 | 
			
		||||
                        c.protected_store.device_encryption_key_password =
 | 
			
		||||
                            new_device_encryption_key_password.clone();
 | 
			
		||||
                        Ok(new_device_encryption_key_password)
 | 
			
		||||
                    })
 | 
			
		||||
                    .unwrap()
 | 
			
		||||
            } else {
 | 
			
		||||
                // Get device encryption key protection password if we have it
 | 
			
		||||
                let c = self.config.get();
 | 
			
		||||
                c.protected_store.device_encryption_key_password.clone()
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        let dek_bytes = self.maybe_protect_device_encryption_key(
 | 
			
		||||
            device_encryption_key,
 | 
			
		||||
            &device_encryption_key_password,
 | 
			
		||||
        )?;
 | 
			
		||||
 | 
			
		||||
        // Save the new device encryption key
 | 
			
		||||
        let existed = self
 | 
			
		||||
            .protected_store
 | 
			
		||||
            .save_user_secret("device_encryption_key", &dek_bytes)
 | 
			
		||||
            .await?;
 | 
			
		||||
        trace!("saving device encryption key. existed: {}", existed);
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								veilid-core/src/table_store/tests/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								veilid-core/src/table_store/tests/mod.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
pub mod test_table_store;
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
use super::test_veilid_config::*;
 | 
			
		||||
use crate::tests::test_veilid_config::*;
 | 
			
		||||
use crate::*;
 | 
			
		||||
 | 
			
		||||
async fn startup() -> VeilidAPI {
 | 
			
		||||
@@ -208,6 +208,56 @@ pub async fn test_json(vcrypto: CryptoSystemVersion, ts: TableStore) {
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn test_protect_unprotect(vcrypto: CryptoSystemVersion, ts: TableStore) {
 | 
			
		||||
    trace!("test_protect_unprotect");
 | 
			
		||||
 | 
			
		||||
    let dek1 = TypedSharedSecret::new(
 | 
			
		||||
        vcrypto.kind(),
 | 
			
		||||
        SharedSecret::new([
 | 
			
		||||
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
			
		||||
            0, 0, 0,
 | 
			
		||||
        ]),
 | 
			
		||||
    );
 | 
			
		||||
    let dek2 = TypedSharedSecret::new(
 | 
			
		||||
        vcrypto.kind(),
 | 
			
		||||
        SharedSecret::new([
 | 
			
		||||
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 | 
			
		||||
            0, 0, 0xFF,
 | 
			
		||||
        ]),
 | 
			
		||||
    );
 | 
			
		||||
    let dek3 = TypedSharedSecret::new(
 | 
			
		||||
        vcrypto.kind(),
 | 
			
		||||
        SharedSecret::new([0x80u8; SHARED_SECRET_LENGTH]),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let deks = [dek1, dek2, dek3];
 | 
			
		||||
    let passwords = ["", " ", "  ", "12345678", "|/\\!@#$%^&*()_+", "Ⓜ️", "🔥🔥♾️"];
 | 
			
		||||
 | 
			
		||||
    for dek in deks {
 | 
			
		||||
        for password in passwords {
 | 
			
		||||
            let dek_bytes = ts
 | 
			
		||||
                .maybe_protect_device_encryption_key(dek, password)
 | 
			
		||||
                .expect(&format!("protect: dek: '{}' pw: '{}'", dek, password));
 | 
			
		||||
            let unprotected = ts
 | 
			
		||||
                .maybe_unprotect_device_encryption_key(&dek_bytes, password)
 | 
			
		||||
                .expect(&format!("unprotect: dek: '{}' pw: '{}'", dek, password));
 | 
			
		||||
            assert_eq!(unprotected, dek);
 | 
			
		||||
            let invalid_password = format!("{}x", password);
 | 
			
		||||
            let _ = ts
 | 
			
		||||
                .maybe_unprotect_device_encryption_key(&dek_bytes, &invalid_password)
 | 
			
		||||
                .expect_err(&format!(
 | 
			
		||||
                    "invalid_password: dek: '{}' pw: '{}'",
 | 
			
		||||
                    dek, &invalid_password
 | 
			
		||||
                ));
 | 
			
		||||
            if password != "" {
 | 
			
		||||
                let _ = ts
 | 
			
		||||
                    .maybe_unprotect_device_encryption_key(&dek_bytes, "")
 | 
			
		||||
                    .expect_err(&format!("empty_password: dek: '{}' pw: ''", dek));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn test_all() {
 | 
			
		||||
    let api = startup().await;
 | 
			
		||||
    let crypto = api.crypto().unwrap();
 | 
			
		||||
@@ -215,6 +265,7 @@ pub async fn test_all() {
 | 
			
		||||
 | 
			
		||||
    for ck in VALID_CRYPTO_KINDS {
 | 
			
		||||
        let vcrypto = crypto.get(ck).unwrap();
 | 
			
		||||
        test_protect_unprotect(vcrypto.clone(), ts.clone()).await;
 | 
			
		||||
        test_delete_open_delete(ts.clone()).await;
 | 
			
		||||
        test_store_delete_load(ts.clone()).await;
 | 
			
		||||
        test_rkyv(vcrypto.clone(), ts.clone()).await;
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
pub mod test_host_interface;
 | 
			
		||||
pub mod test_protected_store;
 | 
			
		||||
pub mod test_table_store;
 | 
			
		||||
pub mod test_veilid_config;
 | 
			
		||||
pub mod test_veilid_core;
 | 
			
		||||
 
 | 
			
		||||
@@ -166,7 +166,7 @@ pub fn setup_veilid_core() -> (UpdateCallback, ConfigCallback) {
 | 
			
		||||
 | 
			
		||||
fn config_callback(key: String) -> ConfigCallbackReturn {
 | 
			
		||||
    match key.as_str() {
 | 
			
		||||
        "program_name" => Ok(Box::new(String::from("Veilid"))),
 | 
			
		||||
        "program_name" => Ok(Box::new(String::from("VeilidCoreTests"))),
 | 
			
		||||
        "namespace" => Ok(Box::new(String::from(""))),
 | 
			
		||||
        "capabilities.protocol_udp" => Ok(Box::new(true)),
 | 
			
		||||
        "capabilities.protocol_connect_tcp" => Ok(Box::new(true)),
 | 
			
		||||
@@ -176,13 +176,17 @@ fn config_callback(key: String) -> ConfigCallbackReturn {
 | 
			
		||||
        "capabilities.protocol_connect_wss" => Ok(Box::new(true)),
 | 
			
		||||
        "capabilities.protocol_accept_wss" => Ok(Box::new(true)),
 | 
			
		||||
        "table_store.directory" => Ok(Box::new(get_table_store_path())),
 | 
			
		||||
        "table_store.delete" => Ok(Box::new(false)),
 | 
			
		||||
        "table_store.delete" => Ok(Box::new(true)),
 | 
			
		||||
        "block_store.directory" => Ok(Box::new(get_block_store_path())),
 | 
			
		||||
        "block_store.delete" => Ok(Box::new(false)),
 | 
			
		||||
        "block_store.delete" => Ok(Box::new(true)),
 | 
			
		||||
        "protected_store.allow_insecure_fallback" => Ok(Box::new(true)),
 | 
			
		||||
        "protected_store.always_use_insecure_storage" => Ok(Box::new(false)),
 | 
			
		||||
        "protected_store.directory" => Ok(Box::new(get_protected_store_path())),
 | 
			
		||||
        "protected_store.delete" => Ok(Box::new(false)),
 | 
			
		||||
        "protected_store.delete" => Ok(Box::new(true)),
 | 
			
		||||
        "protected_store.device_encryption_key_password" => Ok(Box::new("".to_owned())),
 | 
			
		||||
        "protected_store.new_device_encryption_key_password" => {
 | 
			
		||||
            Ok(Box::new(Option::<String>::None))
 | 
			
		||||
        }
 | 
			
		||||
        "network.connection_initial_timeout_ms" => Ok(Box::new(2_000u32)),
 | 
			
		||||
        "network.connection_inactivity_timeout_ms" => Ok(Box::new(60_000u32)),
 | 
			
		||||
        "network.max_connections_per_ip4" => Ok(Box::new(8u32)),
 | 
			
		||||
@@ -302,13 +306,21 @@ pub async fn test_config() {
 | 
			
		||||
    assert_eq!(inner.capabilities.protocol_connect_wss, true);
 | 
			
		||||
    assert_eq!(inner.capabilities.protocol_accept_wss, true);
 | 
			
		||||
    assert_eq!(inner.table_store.directory, get_table_store_path());
 | 
			
		||||
    assert_eq!(inner.table_store.delete, false);
 | 
			
		||||
    assert_eq!(inner.table_store.delete, true);
 | 
			
		||||
    assert_eq!(inner.block_store.directory, get_block_store_path());
 | 
			
		||||
    assert_eq!(inner.block_store.delete, false);
 | 
			
		||||
    assert_eq!(inner.block_store.delete, true);
 | 
			
		||||
    assert_eq!(inner.protected_store.allow_insecure_fallback, true);
 | 
			
		||||
    assert_eq!(inner.protected_store.always_use_insecure_storage, false);
 | 
			
		||||
    assert_eq!(inner.protected_store.directory, get_protected_store_path());
 | 
			
		||||
    assert_eq!(inner.protected_store.delete, false);
 | 
			
		||||
    assert_eq!(inner.protected_store.delete, true);
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        inner.protected_store.device_encryption_key_password,
 | 
			
		||||
        "".to_owned()
 | 
			
		||||
    );
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        inner.protected_store.new_device_encryption_key_password,
 | 
			
		||||
        Option::<String>::None
 | 
			
		||||
    );
 | 
			
		||||
    assert_eq!(inner.network.connection_initial_timeout_ms, 2_000u32);
 | 
			
		||||
    assert_eq!(inner.network.connection_inactivity_timeout_ms, 60_000u32);
 | 
			
		||||
    assert_eq!(inner.network.max_connections_per_ip4, 8u32);
 | 
			
		||||
 
 | 
			
		||||
@@ -13,4 +13,5 @@ pub use common::*;
 | 
			
		||||
pub use crypto::tests::*;
 | 
			
		||||
pub use network_manager::tests::*;
 | 
			
		||||
pub use routing_table::tests::*;
 | 
			
		||||
pub use table_store::tests::*;
 | 
			
		||||
pub use veilid_api::tests::*;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
use crate::crypto::tests::*;
 | 
			
		||||
use crate::network_manager::tests::*;
 | 
			
		||||
use crate::routing_table;
 | 
			
		||||
use crate::table_store::tests::*;
 | 
			
		||||
use crate::tests::common::*;
 | 
			
		||||
use crate::veilid_api;
 | 
			
		||||
use crate::*;
 | 
			
		||||
 
 | 
			
		||||
@@ -734,6 +734,9 @@ impl VeilidConfig {
 | 
			
		||||
 | 
			
		||||
        // Remove secrets
 | 
			
		||||
        safe_cfg.network.routing_table.node_id_secret = TypedSecretSet::new();
 | 
			
		||||
        safe_cfg.protected_store.device_encryption_key_password = "".to_owned();
 | 
			
		||||
        safe_cfg.protected_store.new_device_encryption_key_password = None;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        safe_cfg
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,8 @@
 | 
			
		||||
//! Test suite for the Web and headless browsers.
 | 
			
		||||
 | 
			
		||||
//XXXXXXXXXXXXXXX
 | 
			
		||||
//XXX DOES NOT WORK.
 | 
			
		||||
 | 
			
		||||
#![cfg(target_arch = "wasm32")]
 | 
			
		||||
 | 
			
		||||
extern crate alloc;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user