mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-01-24 05:31:04 -05:00
test work
This commit is contained in:
parent
5b0bfcef48
commit
5f8b440d84
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;
|
||||
|
Loading…
Reference in New Issue
Block a user