webterm_agent/models/
frontend.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crate::config::DEFAULT_PBKDF2_ITERATIONS;
use crate::models::agent_error::AgentError;
use crate::models::session::Session;
use std::sync::Arc;
use tokio::sync::Mutex;
use webterm_core::constants::{BITS256_ZERO, BITS96_ZERO};
use webterm_core::cryptography::cryptographer::Cryptographer;
use webterm_core::random::random_bytes;
use webterm_core::types::{Bits256, Bits96, FrontendId};

pub struct Frontend {
    frontend_id: FrontendId,
    session: Option<Arc<Mutex<Session>>>,
    salt: Bits256,
    cryptographer: Option<Cryptographer>,
    pbkdf2_iterations: u32,
    challenge_nonce: Option<Bits256>,
}

impl Frontend {
    pub fn new(frontend_id: FrontendId) -> Self {
        let mut salt = BITS256_ZERO;
        random_bytes(&mut salt.0);

        // TODO: Guarantee that it will never be reused in IvCounter for this session
        let mut challenge_iv = BITS96_ZERO;
        random_bytes(&mut challenge_iv.0);

        let mut challenge_nonce = BITS256_ZERO;
        random_bytes(&mut challenge_nonce.0);

        Self {
            frontend_id,
            session: None,
            salt,
            cryptographer: None,
            pbkdf2_iterations: DEFAULT_PBKDF2_ITERATIONS,
            challenge_nonce: Some(challenge_nonce),
        }
    }

    pub fn frontend_id(&self) -> FrontendId {
        self.frontend_id
    }

    pub fn register_session(&mut self, session: Arc<Mutex<Session>>) {
        self.session = Some(session);
    }

    pub async fn session(&self) -> Result<Arc<Mutex<Session>>, AgentError> {
        Ok(self
            .session
            .as_ref()
            .ok_or(AgentError::SessionNotFound(None))?
            .clone())
    }

    pub fn init_cryptographer(&mut self, secret_key: &str) {
        self.cryptographer = Some(Cryptographer::new(
            self.salt,
            secret_key,
            self.pbkdf2_iterations,
        ))
    }

    pub fn cryptographer(&self) -> Result<&Cryptographer, AgentError> {
        self.cryptographer.as_ref().ok_or(AgentError::RuntimeError(
            "Cryptographer is not initialised".to_string(),
        ))
    }

    pub fn verify_and_consume_nonce(
        &mut self,
        encrypted_nonce: &Bits256,
        iv: &Bits96,
    ) -> Result<bool, AgentError> {
        if let Some(challenge_nonce) = self.challenge_nonce {
            let decrypted_nonce =
                self.cryptographer()?
                    .decrypt(encrypted_nonce.0.as_ref(), iv, false)?;
            let result = challenge_nonce.0.to_vec() == decrypted_nonce;
            self.challenge_nonce = None;
            Ok(result)
        } else {
            Err(AgentError::RuntimeError(
                "Challenge nonce is not set".to_string(),
            ))
        }
    }

    pub fn salt(&self) -> Bits256 {
        self.salt
    }

    pub fn pbkdf2_iterations(&self) -> u32 {
        self.pbkdf2_iterations
    }

    pub fn challenge_nonce(&self) -> Result<Bits256, AgentError> {
        self.challenge_nonce.ok_or(AgentError::RuntimeError(
            "Challenge nonce is not set".to_string(),
        ))
    }
}