snow/
stateless_transportstate.rs1use crate::{
2 cipherstate::StatelessCipherStates,
3 constants::{MAXDHLEN, MAXMSGLEN, TAGLEN},
4 error::{Error, StateProblem},
5 handshakestate::HandshakeState,
6 params::HandshakePattern,
7 utils::Toggle,
8};
9use std::{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 pub fn get_remote_static(&self) -> Option<&[u8]> {
44 self.rs.get().map(|rs| &rs[..self.dh_len])
45 }
46
47 pub fn write_message(
57 &self,
58 nonce: u64,
59 payload: &[u8],
60 message: &mut [u8],
61 ) -> Result<usize, Error> {
62 if !self.initiator && self.pattern.is_oneway() {
63 return Err(StateProblem::OneWay.into());
64 } else if payload.len() + TAGLEN > MAXMSGLEN || payload.len() + TAGLEN > message.len() {
65 return Err(Error::Input);
66 }
67
68 let cipher = if self.initiator { &self.cipherstates.0 } else { &self.cipherstates.1 };
69 cipher.encrypt(nonce, payload, message)
70 }
71
72 pub fn read_message(
83 &self,
84 nonce: u64,
85 payload: &[u8],
86 message: &mut [u8],
87 ) -> Result<usize, Error> {
88 if payload.len() > MAXMSGLEN {
89 Err(Error::Input)
90 } else if self.initiator && self.pattern.is_oneway() {
91 Err(StateProblem::OneWay.into())
92 } else {
93 let cipher = if self.initiator { &self.cipherstates.1 } else { &self.cipherstates.0 };
94 cipher.decrypt(nonce, payload, message)
95 }
96 }
97
98 pub fn rekey_outgoing(&mut self) {
103 if self.initiator {
104 self.cipherstates.rekey_initiator()
105 } else {
106 self.cipherstates.rekey_responder()
107 }
108 }
109
110 pub fn rekey_incoming(&mut self) {
115 if self.initiator {
116 self.cipherstates.rekey_responder()
117 } else {
118 self.cipherstates.rekey_initiator()
119 }
120 }
121
122 pub fn rekey_manually(&mut self, initiator: Option<&[u8]>, responder: Option<&[u8]>) {
124 if let Some(key) = initiator {
125 self.rekey_initiator_manually(key);
126 }
127 if let Some(key) = responder {
128 self.rekey_responder_manually(key);
129 }
130 }
131
132 pub fn rekey_initiator_manually(&mut self, key: &[u8]) {
134 self.cipherstates.rekey_initiator_manually(key)
135 }
136
137 pub fn rekey_responder_manually(&mut self, key: &[u8]) {
139 self.cipherstates.rekey_responder_manually(key)
140 }
141
142 pub fn is_initiator(&self) -> bool {
144 self.initiator
145 }
146}
147
148impl fmt::Debug for StatelessTransportState {
149 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
150 fmt.debug_struct("StatelessTransportState").finish()
151 }
152}
153
154impl TryFrom<HandshakeState> for StatelessTransportState {
155 type Error = Error;
156
157 fn try_from(old: HandshakeState) -> Result<Self, Self::Error> {
158 StatelessTransportState::new(old)
159 }
160}