webterm_agent/models/
frontend.rs1use 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 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}