1use crate::util::Threading;
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5#[error("{0}")]
6pub struct ConfigError(pub String);
7
8#[derive(Default, Clone, Debug, serde::Serialize, serde::Deserialize)]
9pub struct NoiseConfigData {
10 pub app_static_privkey: Option<[u8; 32]>,
11 pub device_static_pubkeys: Vec<Vec<u8>>,
12}
13
14impl NoiseConfigData {
15 pub(crate) fn contains_device_static_pubkey(&self, pubkey: &[u8]) -> bool {
16 self.device_static_pubkeys
17 .iter()
18 .any(|config_pubkey| config_pubkey.as_slice() == pubkey)
19 }
20
21 pub(crate) fn add_device_static_pubkey(&mut self, pubkey: &[u8]) {
22 if !self.contains_device_static_pubkey(pubkey) {
23 self.device_static_pubkeys.push(pubkey.to_vec());
24 }
25 }
26
27 pub(crate) fn get_app_static_privkey(&self) -> Option<zeroize::Zeroizing<[u8; 32]>> {
28 self.app_static_privkey.map(zeroize::Zeroizing::new)
31 }
32
33 pub(crate) fn set_app_static_privkey(&mut self, privkey: &[u8]) -> Result<(), ConfigError> {
34 self.app_static_privkey = Some(
35 privkey
36 .try_into()
37 .map_err(|e: std::array::TryFromSliceError| ConfigError(e.to_string()))?,
38 );
39 Ok(())
40 }
41}
42
43pub trait NoiseConfig: Threading {
44 fn read_config(&self) -> Result<NoiseConfigData, ConfigError> {
45 Ok(NoiseConfigData::default())
46 }
47 fn store_config(&self, _conf: &NoiseConfigData) -> Result<(), ConfigError> {
48 Ok(())
49 }
50}
51
52pub struct NoiseConfigNoCache;
53impl NoiseConfig for NoiseConfigNoCache {}
54impl Threading for NoiseConfigNoCache {}
55
56pub struct PersistedNoiseConfig {
57 config_dir: String,
58}
59
60impl Threading for PersistedNoiseConfig {}
61
62impl PersistedNoiseConfig {
63 pub fn new(config_dir: &str) -> PersistedNoiseConfig {
66 PersistedNoiseConfig {
67 config_dir: config_dir.into(),
68 }
69 }
70}
71
72impl NoiseConfig for PersistedNoiseConfig {
73 fn read_config(&self) -> Result<NoiseConfigData, ConfigError> {
74 use std::io::Read;
75
76 let config_path = std::path::Path::new(&self.config_dir).join("bitbox.json");
77
78 if !config_path.exists() {
79 return Ok(NoiseConfigData::default());
80 }
81
82 let mut file = std::fs::File::open(config_path).map_err(|e| ConfigError(e.to_string()))?;
83
84 let mut contents = String::new();
85 file.read_to_string(&mut contents)
86 .map_err(|e| ConfigError(e.to_string()))?;
87
88 serde_json::from_str::<NoiseConfigData>(&contents).map_err(|e| ConfigError(e.to_string()))
89 }
90
91 fn store_config(&self, conf: &NoiseConfigData) -> Result<(), ConfigError> {
92 use std::io::Write;
93
94 let config_path = std::path::Path::new(&self.config_dir).join("bitbox.json");
95
96 let mut file =
97 std::fs::File::create(config_path).map_err(|e| ConfigError(e.to_string()))?;
98
99 let data = serde_json::to_string(conf).map_err(|e| ConfigError(e.to_string()))?;
100
101 file.write_all(data.as_bytes())
102 .map_err(|e| ConfigError(e.to_string()))
103 }
104}