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