snow/
stateless_transportstate.rs1use crate::{
2 cipherstate::StatelessCipherStates,
3 constants::{CIPHERKEYLEN, MAXDHLEN, MAXMSGLEN, TAGLEN},
4 error::{Error, StateProblem},
5 handshakestate::HandshakeState,
6 params::HandshakePattern,
7 utils::Toggle,
8};
9use core::{convert::TryFrom, fmt};
10
11pub struct StatelessTransportState {
17 cipherstates: StatelessCipherStates,
18 pattern: HandshakePattern,
19 dh_len: usize,
20 rs: Toggle<[u8; MAXDHLEN]>,
21 initiator: bool,
22}
23
24impl StatelessTransportState {
25 pub(crate) fn new(handshake: HandshakeState) -> Result<Self, Error> {
26 if !handshake.is_handshake_finished() {
27 return Err(StateProblem::HandshakeNotFinished.into());
28 }
29
30 let dh_len = handshake.dh_len();
31 let HandshakeState { cipherstates, params, rs, initiator, .. } = handshake;
32 let pattern = params.handshake.pattern;
33
34 Ok(Self { cipherstates: cipherstates.into(), pattern, dh_len, rs, initiator })
35 }
36
37 #[must_use]
44 pub fn get_remote_static(&self) -> Option<&[u8]> {
45 self.rs.get().map(|rs| &rs[..self.dh_len])
46 }
47
48 pub fn write_message(
58 &self,
59 nonce: u64,
60 payload: &[u8],
61 message: &mut [u8],
62 ) -> Result<usize, Error> {
63 if !self.initiator && self.pattern.is_oneway() {
64 return Err(StateProblem::OneWay.into());
65 } else if payload.len() + TAGLEN > MAXMSGLEN || payload.len() + TAGLEN > message.len() {
66 return Err(Error::Input);
67 }
68
69 let cipher = if self.initiator { &self.cipherstates.0 } else { &self.cipherstates.1 };
70 cipher.encrypt(nonce, payload, message)
71 }
72
73 pub fn read_message(
85 &self,
86 nonce: u64,
87 payload: &[u8],
88 message: &mut [u8],
89 ) -> Result<usize, Error> {
90 if payload.len() > MAXMSGLEN {
91 Err(Error::Input)
92 } else if self.initiator && self.pattern.is_oneway() {
93 Err(StateProblem::OneWay.into())
94 } else {
95 let cipher = if self.initiator { &self.cipherstates.1 } else { &self.cipherstates.0 };
96 cipher.decrypt(nonce, payload, message)
97 }
98 }
99
100 pub fn rekey_outgoing(&mut self) {
105 if self.initiator {
106 self.cipherstates.rekey_initiator();
107 } else {
108 self.cipherstates.rekey_responder();
109 }
110 }
111
112 pub fn rekey_incoming(&mut self) {
117 if self.initiator {
118 self.cipherstates.rekey_responder();
119 } else {
120 self.cipherstates.rekey_initiator();
121 }
122 }
123
124 pub fn rekey_manually(
126 &mut self,
127 initiator: Option<&[u8; CIPHERKEYLEN]>,
128 responder: Option<&[u8; CIPHERKEYLEN]>,
129 ) {
130 if let Some(key) = initiator {
131 self.rekey_initiator_manually(key);
132 }
133 if let Some(key) = responder {
134 self.rekey_responder_manually(key);
135 }
136 }
137
138 pub fn rekey_initiator_manually(&mut self, key: &[u8; CIPHERKEYLEN]) {
140 self.cipherstates.rekey_initiator_manually(key);
141 }
142
143 pub fn rekey_responder_manually(&mut self, key: &[u8; CIPHERKEYLEN]) {
145 self.cipherstates.rekey_responder_manually(key);
146 }
147
148 #[must_use]
150 pub fn is_initiator(&self) -> bool {
151 self.initiator
152 }
153}
154
155impl fmt::Debug for StatelessTransportState {
156 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
157 fmt.debug_struct("StatelessTransportState").finish()
158 }
159}
160
161impl TryFrom<HandshakeState> for StatelessTransportState {
162 type Error = Error;
163
164 fn try_from(old: HandshakeState) -> Result<Self, Self::Error> {
165 StatelessTransportState::new(old)
166 }
167}