snow/
cipherstate.rs

1use crate::{
2    constants::TAGLEN,
3    error::{Error, InitStage, StateProblem},
4    types::Cipher,
5};
6
7pub(crate) struct CipherState {
8    cipher:  Box<dyn Cipher>,
9    n:       u64,
10    has_key: bool,
11}
12
13impl CipherState {
14    pub fn new(cipher: Box<dyn Cipher>) -> Self {
15        Self { cipher, n: 0, has_key: false }
16    }
17
18    pub fn name(&self) -> &'static str {
19        self.cipher.name()
20    }
21
22    pub fn set(&mut self, key: &[u8], n: u64) {
23        self.cipher.set(key);
24        self.n = n;
25        self.has_key = true;
26    }
27
28    pub fn encrypt_ad(
29        &mut self,
30        authtext: &[u8],
31        plaintext: &[u8],
32        out: &mut [u8],
33    ) -> Result<usize, Error> {
34        if !self.has_key {
35            return Err(StateProblem::MissingKeyMaterial.into());
36        }
37
38        validate_nonce(self.n)?;
39        let len = self.cipher.encrypt(self.n, authtext, plaintext, out);
40
41        // We have validated this will not wrap around.
42        self.n += 1;
43
44        Ok(len)
45    }
46
47    pub fn decrypt_ad(
48        &mut self,
49        authtext: &[u8],
50        ciphertext: &[u8],
51        out: &mut [u8],
52    ) -> Result<usize, Error> {
53        if (ciphertext.len() < TAGLEN) || out.len() < (ciphertext.len() - TAGLEN) {
54            return Err(Error::Decrypt);
55        }
56
57        if !self.has_key {
58            return Err(StateProblem::MissingKeyMaterial.into());
59        }
60
61        validate_nonce(self.n)?;
62        let len = self.cipher.decrypt(self.n, authtext, ciphertext, out)?;
63
64        // We have validated this will not wrap around.
65        self.n += 1;
66
67        Ok(len)
68    }
69
70    pub fn encrypt(&mut self, plaintext: &[u8], out: &mut [u8]) -> Result<usize, Error> {
71        self.encrypt_ad(&[0u8; 0], plaintext, out)
72    }
73
74    pub fn decrypt(&mut self, ciphertext: &[u8], out: &mut [u8]) -> Result<usize, Error> {
75        self.decrypt_ad(&[0u8; 0], ciphertext, out)
76    }
77
78    pub fn rekey(&mut self) {
79        self.cipher.rekey();
80    }
81
82    pub fn rekey_manually(&mut self, key: &[u8]) {
83        self.cipher.set(key);
84    }
85
86    pub fn nonce(&self) -> u64 {
87        self.n
88    }
89
90    pub fn set_nonce(&mut self, nonce: u64) {
91        self.n = nonce;
92    }
93}
94
95pub(crate) struct CipherStates(pub CipherState, pub CipherState);
96
97impl CipherStates {
98    pub fn new(initiator: CipherState, responder: CipherState) -> Result<Self, Error> {
99        if initiator.name() != responder.name() {
100            return Err(InitStage::ValidateCipherTypes.into());
101        }
102
103        Ok(CipherStates(initiator, responder))
104    }
105
106    pub fn rekey_initiator(&mut self) {
107        self.0.rekey()
108    }
109
110    pub fn rekey_initiator_manually(&mut self, key: &[u8]) {
111        self.0.rekey_manually(key)
112    }
113
114    pub fn rekey_responder(&mut self) {
115        self.1.rekey()
116    }
117
118    pub fn rekey_responder_manually(&mut self, key: &[u8]) {
119        self.1.rekey_manually(key)
120    }
121}
122
123pub(crate) struct StatelessCipherState {
124    cipher:  Box<dyn Cipher>,
125    has_key: bool,
126}
127
128impl StatelessCipherState {
129    pub fn encrypt_ad(
130        &self,
131        nonce: u64,
132        authtext: &[u8],
133        plaintext: &[u8],
134        out: &mut [u8],
135    ) -> Result<usize, Error> {
136        if !self.has_key {
137            return Err(StateProblem::MissingKeyMaterial.into());
138        }
139
140        validate_nonce(nonce)?;
141
142        Ok(self.cipher.encrypt(nonce, authtext, plaintext, out))
143    }
144
145    pub fn decrypt_ad(
146        &self,
147        nonce: u64,
148        authtext: &[u8],
149        ciphertext: &[u8],
150        out: &mut [u8],
151    ) -> Result<usize, Error> {
152        if (ciphertext.len() < TAGLEN) || out.len() < (ciphertext.len() - TAGLEN) {
153            return Err(Error::Decrypt);
154        }
155
156        if !self.has_key {
157            return Err(StateProblem::MissingKeyMaterial.into());
158        }
159
160        validate_nonce(nonce)?;
161
162        self.cipher.decrypt(nonce, authtext, ciphertext, out)
163    }
164
165    pub fn encrypt(&self, nonce: u64, plaintext: &[u8], out: &mut [u8]) -> Result<usize, Error> {
166        self.encrypt_ad(nonce, &[], plaintext, out)
167    }
168
169    pub fn decrypt(&self, nonce: u64, ciphertext: &[u8], out: &mut [u8]) -> Result<usize, Error> {
170        self.decrypt_ad(nonce, &[], ciphertext, out)
171    }
172
173    pub fn rekey(&mut self) {
174        self.cipher.rekey()
175    }
176
177    pub fn rekey_manually(&mut self, key: &[u8]) {
178        self.cipher.set(key);
179    }
180}
181
182/// Validates that a nonce value has not exceeded the maximum
183/// defined by the Noise spec.
184fn validate_nonce(current: u64) -> Result<(), Error> {
185    // 2^64-1 is reserved and may not be used in the state machine (5.1).
186    //
187    // It is used by the default cipher rekey function (4.2).
188    if current == u64::MAX {
189        Err(Error::State(StateProblem::Exhausted))
190    } else {
191        Ok(())
192    }
193}
194
195impl From<CipherState> for StatelessCipherState {
196    fn from(other: CipherState) -> Self {
197        Self { cipher: other.cipher, has_key: other.has_key }
198    }
199}
200
201pub(crate) struct StatelessCipherStates(pub StatelessCipherState, pub StatelessCipherState);
202
203impl From<CipherStates> for StatelessCipherStates {
204    fn from(other: CipherStates) -> Self {
205        StatelessCipherStates(other.0.into(), other.1.into())
206    }
207}
208
209impl StatelessCipherStates {
210    pub fn rekey_initiator(&mut self) {
211        self.0.rekey()
212    }
213
214    pub fn rekey_initiator_manually(&mut self, key: &[u8]) {
215        self.0.rekey_manually(key)
216    }
217
218    pub fn rekey_responder(&mut self) {
219        self.1.rekey()
220    }
221
222    pub fn rekey_responder_manually(&mut self, key: &[u8]) {
223        self.1.rekey_manually(key)
224    }
225}