Skip to content

Commit

Permalink
TransportState: limit read_message size to 65535
Browse files Browse the repository at this point in the history
While not really a big issue since applications should be checking
message sizes over the wire as well, this could theoretically allow for
DoS's by asking snow to decrypt messages larger than the Noise Protocol
specification allows.
  • Loading branch information
mcginty committed Jan 26, 2024
1 parent faf0560 commit 9e53dcf
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 11 deletions.
11 changes: 7 additions & 4 deletions src/stateless_transportstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,14 @@ impl StatelessTransportState {
payload: &[u8],
message: &mut [u8],
) -> Result<usize, Error> {
if self.initiator && self.pattern.is_oneway() {
return Err(StateProblem::OneWay.into());
if payload.len() > MAXMSGLEN {
Err(Error::Input)
} else if self.initiator && self.pattern.is_oneway() {
Err(StateProblem::OneWay.into())
} else {
let cipher = if self.initiator { &self.cipherstates.1 } else { &self.cipherstates.0 };
cipher.decrypt(nonce, payload, message)
}
let cipher = if self.initiator { &self.cipherstates.1 } else { &self.cipherstates.0 };
cipher.decrypt(nonce, payload, message)
}

/// Generates a new key for the egress symmetric cipher according to Section 4.2
Expand Down
14 changes: 8 additions & 6 deletions src/transportstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@ impl TransportState {
///
/// Will result in `StateProblem::Exhausted` if the max nonce overflows.
pub fn read_message(&mut self, payload: &[u8], message: &mut [u8]) -> Result<usize, Error> {
if self.initiator && self.pattern.is_oneway() {
return Err(StateProblem::OneWay.into());
if payload.len() > MAXMSGLEN {
Err(Error::Input)
} else if self.initiator && self.pattern.is_oneway() {
Err(StateProblem::OneWay.into())
} else {
let cipher =
if self.initiator { &mut self.cipherstates.1 } else { &mut self.cipherstates.0 };
cipher.decrypt(payload, message)
}
let cipher =
if self.initiator { &mut self.cipherstates.1 } else { &mut self.cipherstates.0 };

cipher.decrypt(payload, message)
}

/// Generates a new key for the egress symmetric cipher according to Section 4.2
Expand Down
30 changes: 29 additions & 1 deletion tests/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use hex::FromHex;
use snow::{
resolvers::{CryptoResolver, DefaultResolver},
Builder,
Builder, Error,
};

use rand_core::{impls, CryptoRng, RngCore};
Expand Down Expand Up @@ -509,6 +509,34 @@ fn test_handshake_message_undersized_output_buffer() {
assert!(h_i.write_message(&[0u8; 400], &mut buffer_out).is_err());
}

#[test]
fn test_handshake_message_receive_oversized_message() {
let params: NoiseParams = "Noise_NN_25519_ChaChaPoly_SHA256".parse().unwrap();
let mut h_i = Builder::new(params.clone()).build_initiator().unwrap();
let mut h_r = Builder::new(params).build_responder().unwrap();

let mut buffer_msg = [0u8; 100_000];
let mut buffer_out = [0u8; 100_000];
let len = h_i.write_message(b"abc", &mut buffer_msg).unwrap();
assert_eq!(Error::Input, h_r.read_message(&buffer_msg, &mut buffer_out).unwrap_err());
h_r.read_message(&buffer_msg[..len], &mut buffer_out).unwrap();

let len = h_r.write_message(b"defg", &mut buffer_msg).unwrap();
h_i.read_message(&buffer_msg[..len], &mut buffer_out).unwrap();

let h_i = h_i.into_stateless_transport_mode().unwrap();
let mut h_r = h_r.into_transport_mode().unwrap();

let len = h_i.write_message(0, b"hack the planet", &mut buffer_msg).unwrap();
assert_eq!(Error::Input, h_r.read_message(&buffer_msg, &mut buffer_out).unwrap_err());
h_r.read_message(&buffer_msg[..len], &mut buffer_out).unwrap();

let len = h_r.write_message(b"hack the planet", &mut buffer_msg).unwrap();
assert_eq!(Error::Input, h_i.read_message(0, &buffer_msg, &mut buffer_out).unwrap_err());
let len = h_i.read_message(0, &buffer_msg[..len], &mut buffer_out).unwrap();
assert_eq!(&buffer_out[..len], b"hack the planet");
}

#[test]
fn test_transport_message_exceeds_max_len() {
let params: NoiseParams = "Noise_N_25519_ChaChaPoly_SHA256".parse().unwrap();
Expand Down

0 comments on commit 9e53dcf

Please sign in to comment.