Skip to content

Commit

Permalink
Add back garbage tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nyonson committed Oct 17, 2024
1 parent 26a8280 commit 72e382f
Showing 1 changed file with 86 additions and 6 deletions.
92 changes: 86 additions & 6 deletions protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ pub const NUM_INITIAL_HANDSHAKE_BUFFER_BYTES: usize = 4096;
const VERSION_CONTENT: [u8; 0] = [];
// Number of bytes for the authentication tag of a packet.
const NUM_TAG_BYTES: usize = 16;
// Maximum number of garbage bytes to read before the terminator.
// Maximum number of garbage bytes before the terminator.
const MAX_NUM_GARBAGE_BYTES: usize = 4095;
// Number of bytes for the garbage terminator.
const NUM_GARBAGE_TERMINTOR_BYTES: usize = 16;
Expand All @@ -85,8 +85,11 @@ pub enum Error {
/// total required bytes for the failed packet so the
/// caller can re-allocate and re-attempt.
BufferTooSmall { required_bytes: usize },
/// The maximum amount of garbage bytes was exceeded in the handshake.
MaxGarbageLength,
/// Tried to send more garbage bytes before terminator than allowed by spec.
TooMuchGarbage,
/// The remote sent the maximum amount of garbage bytes without
/// a garbage terminator in the handshake.
NoGarbageTerminator,
/// A handshake step was not completed in the proper order.
HandshakeOutOfOrder,
/// The remote peer is communicating on the V1 protocol.
Expand All @@ -111,13 +114,17 @@ impl fmt::Display for Error {
"Buffer memory allocation too small, need at least {} bytes.",
required_bytes
),
Error::MaxGarbageLength => {
write!(f, "More than 4095 bytes of garbage in the handshake.")
Error::NoGarbageTerminator => {
write!(f, "More than 4095 bytes of garbage recieved in the handshake before a terminator was sent.")
}
Error::HandshakeOutOfOrder => write!(f, "Handshake flow out of sequence."),
Error::SecretGeneration(e) => write!(f, "Cannot generate secrets: {:?}.", e),
Error::Decryption(e) => write!(f, "Decrytion error: {:?}.", e),
Error::V1Protocol => write!(f, "The remote peer is communicating on the V1 protocol."),
Error::TooMuchGarbage => write!(
f,
"Tried to send more than 4095 bytes of garbage in handshake."
),
}
}
}
Expand Down Expand Up @@ -627,6 +634,13 @@ impl<'a> Handshake<'a> {
rng: &mut impl Rng,
curve: &Secp256k1<C>,
) -> Result<Self, Error> {
if garbage
.as_ref()
.map_or(false, |g| g.len() > MAX_NUM_GARBAGE_BYTES)
{
return Err(Error::TooMuchGarbage);
};

let mut secret_key_buffer = [0u8; 32];
rng.fill(&mut secret_key_buffer[..]);
let sk = SecretKey::from_slice(&secret_key_buffer)?;
Expand Down Expand Up @@ -920,7 +934,7 @@ impl<'a> Handshake<'a> {
{
Ok((&buffer[..index], &buffer[(index + garbage_term.len())..]))
} else if buffer.len() >= (MAX_NUM_GARBAGE_BYTES + NUM_GARBAGE_TERMINTOR_BYTES) {
Err(Error::MaxGarbageLength)
Err(Error::NoGarbageTerminator)
} else {
// Terminator not found, the buffer needs more information.
Err(Error::CiphertextTooSmall)
Expand Down Expand Up @@ -1481,7 +1495,54 @@ mod tests {

#[test]
#[cfg(feature = "std")]
<<<<<<< HEAD
fn test_handshake_v1_protocol() {
=======
fn test_handshake_garbage_length_check() {
let mut rng = rand::thread_rng();
let curve = Secp256k1::new();
let mut handshake_buffer = [0u8; NUM_ELLIGATOR_SWIFT_BYTES + MAX_NUM_GARBAGE_BYTES];

// Test with valid garbage length.
let valid_garbage = vec![0u8; MAX_NUM_GARBAGE_BYTES];
let result = Handshake::new_with_rng(
Network::Bitcoin,
Role::Initiator,
Some(&valid_garbage),
&mut handshake_buffer,
&mut rng,
&curve,
);
assert!(result.is_ok());

// Test with garbage length exceeding MAX_NUM_GARBAGE_BYTES.
let invalid_garbage = vec![0u8; MAX_NUM_GARBAGE_BYTES + 1];
let result = Handshake::new_with_rng(
Network::Bitcoin,
Role::Initiator,
Some(&invalid_garbage),
&mut handshake_buffer,
&mut rng,
&curve,
);
assert!(matches!(result, Err(Error::TooMuchGarbage)));

// Test with no garbage.
let result = Handshake::new_with_rng(
Network::Bitcoin,
Role::Initiator,
None,
&mut handshake_buffer,
&mut rng,
&curve,
);
assert!(result.is_ok());
}

#[test]
#[cfg(feature = "std")]
fn test_handshake_no_garbage_terminator() {
>>>>>>> de4a25e (Add back garbage tests)
let mut handshake_buffer = [0u8; NUM_ELLIGATOR_SWIFT_BYTES];
let mut rng = rand::thread_rng();
let curve = Secp256k1::signing_only();
Expand All @@ -1496,17 +1557,36 @@ mod tests {
)
.expect("Handshake creation should succeed");

<<<<<<< HEAD
// Emulate remote sending network magic for start of V1 protocol.
let mut v1_protocol = [0u8; NUM_ELLIGATOR_SWIFT_BYTES];
v1_protocol[..4].copy_from_slice(&Network::Bitcoin.magic().to_bytes()[..]);
let mut response_buffer = [0u8; 0];
let result = handshake.complete_materials(v1_protocol, &mut response_buffer, None);
assert!(matches!(result, Err(Error::V1Protocol)));
=======
// Skipping material creation and just placing a mock terminator.
handshake.remote_garbage_terminator = Some([0xFF; NUM_GARBAGE_TERMINTOR_BYTES]);

// Test with a buffer that is too long.
let test_buffer = vec![0; MAX_NUM_GARBAGE_BYTES + NUM_GARBAGE_TERMINTOR_BYTES];
let result = handshake.split_garbage(&test_buffer);
assert!(matches!(result, Err(Error::NoGarbageTerminator)));

// Test with a buffer that's just short of the required length.
let short_buffer = vec![0; MAX_NUM_GARBAGE_BYTES + NUM_GARBAGE_TERMINTOR_BYTES - 1];
let result = handshake.split_garbage(&short_buffer);
assert!(matches!(result, Err(Error::CiphertextTooSmall)));
>>>>>>> de4a25e (Add back garbage tests)
}

#[test]
#[cfg(feature = "std")]
<<<<<<< HEAD
fn test_full_handshake_with_garbage_and_decoys() {
=======
fn test_handshake_with_garbage_and_decoys() {
>>>>>>> de4a25e (Add back garbage tests)
// Define the garbage and decoys that the initiator is sending to the responder.
let initiator_garbage = vec![1u8, 2u8, 3u8];
let initiator_decoys: Vec<&[u8]> = vec![&[6u8, 7u8], &[8u8, 0u8]];
Expand Down

0 comments on commit 72e382f

Please sign in to comment.