webterm_agent/models/
frontend.rs

1use crate::config::DEFAULT_PBKDF2_ITERATIONS;
2use crate::models::agent_error::AgentError;
3use crate::models::session::Session;
4use std::sync::Arc;
5use tokio::sync::Mutex;
6use webterm_core::constants::{BITS256_ZERO, BITS96_ZERO};
7use webterm_core::cryptography::cryptographer::Cryptographer;
8use webterm_core::random::random_bytes;
9use webterm_core::types::{Bits256, Bits96, FrontendId};
10
11pub struct Frontend {
12    frontend_id: FrontendId,
13    session: Option<Arc<Mutex<Session>>>,
14    salt: Bits256,
15    cryptographer: Option<Cryptographer>,
16    pbkdf2_iterations: u32,
17    challenge_nonce: Option<Bits256>,
18}
19
20impl Frontend {
21    pub fn new(frontend_id: FrontendId) -> Self {
22        let mut salt = BITS256_ZERO;
23        random_bytes(&mut salt.0);
24
25        // TODO: Guarantee that it will never be reused in IvCounter for this session
26        let mut challenge_iv = BITS96_ZERO;
27        random_bytes(&mut challenge_iv.0);
28
29        let mut challenge_nonce = BITS256_ZERO;
30        random_bytes(&mut challenge_nonce.0);
31
32        Self {
33            frontend_id,
34            session: None,
35            salt,
36            cryptographer: None,
37            pbkdf2_iterations: DEFAULT_PBKDF2_ITERATIONS,
38            challenge_nonce: Some(challenge_nonce),
39        }
40    }
41
42    pub fn frontend_id(&self) -> FrontendId {
43        self.frontend_id
44    }
45
46    pub fn register_session(&mut self, session: Arc<Mutex<Session>>) {
47        self.session = Some(session);
48    }
49
50    pub async fn session(&self) -> Result<Arc<Mutex<Session>>, AgentError> {
51        Ok(self
52            .session
53            .as_ref()
54            .ok_or(AgentError::SessionNotFound(None))?
55            .clone())
56    }
57
58    pub fn init_cryptographer(&mut self, secret_key: &str) {
59        self.cryptographer = Some(Cryptographer::new(
60            self.salt,
61            secret_key,
62            self.pbkdf2_iterations,
63        ))
64    }
65
66    pub fn cryptographer(&self) -> Result<&Cryptographer, AgentError> {
67        self.cryptographer.as_ref().ok_or(AgentError::RuntimeError(
68            "Cryptographer is not initialised".to_string(),
69        ))
70    }
71
72    pub fn verify_and_consume_nonce(
73        &mut self,
74        encrypted_nonce: &Bits256,
75        iv: &Bits96,
76    ) -> Result<bool, AgentError> {
77        if let Some(challenge_nonce) = self.challenge_nonce {
78            let decrypted_nonce =
79                self.cryptographer()?
80                    .decrypt(encrypted_nonce.0.as_ref(), iv, false)?;
81            let result = challenge_nonce.0.to_vec() == decrypted_nonce;
82            self.challenge_nonce = None;
83            Ok(result)
84        } else {
85            Err(AgentError::RuntimeError(
86                "Challenge nonce is not set".to_string(),
87            ))
88        }
89    }
90
91    pub fn salt(&self) -> Bits256 {
92        self.salt
93    }
94
95    pub fn pbkdf2_iterations(&self) -> u32 {
96        self.pbkdf2_iterations
97    }
98
99    pub fn challenge_nonce(&self) -> Result<Bits256, AgentError> {
100        self.challenge_nonce.ok_or(AgentError::RuntimeError(
101            "Challenge nonce is not set".to_string(),
102        ))
103    }
104}