message: Add test case for security issue from str4d/rage#195
diff: @@ -808,4 +808,50 @@ mod tests {
  r.read_exact(&mut buf).unwrap();
  assert_eq!(&buf[..], &data[data.len() - 1337..data.len() - 1237]);
  }
  +
  + #[test]
  + fn seek_from_end_fails_on_truncation() {
  + // The plaintext is the string "hello" followed by 65536 zeros, just enough to
  + // give us some bytes to play with in the second chunk.
  + let mut plaintext: Vec<u8> = b"hello".to_vec();
  + plaintext.extend_from_slice(&[0; 65536]);
  +
  + // Encrypt the plaintext just like the example code in the docs.
  + let mut encrypted = vec![];
  + {
  + let mut w = Stream::encrypt(PayloadKey([7; 32].into()), &mut encrypted);
  + w.write_all(&plaintext).unwrap();
  + w.finish().unwrap();
  + };
  +
  + // First check the correct behavior of seeks relative to EOF. Create a decrypting
  + // reader, and move it one byte forward from the start, using SeekFrom::End.
  + // Confirm that reading 4 bytes from that point gives us "ello", as it should.
  + let mut reader = Stream::decrypt(PayloadKey([7; 32].into()), Cursor::new(&encrypted));
  + let eof_relative_offset = 1 as i64 - plaintext.len() as i64;
  + reader.seek(SeekFrom::End(eof_relative_offset)).unwrap();
  + let mut buf = [0; 4];
  + reader.read_exact(&mut buf).unwrap();
  + assert_eq!(&buf, b"ello", "This is correct.");
  +
  + // Do the same thing again, except this time truncate the ciphertext by one byte
  + // first. This should cause some sort of error, instead of a successful read that
  + // returns the wrong plaintext.
  + let truncated_ciphertext = &encrypted[..encrypted.len() - 1];
  + let mut truncated_reader = Stream::decrypt(
  + PayloadKey([7; 32].into()),
  + Cursor::new(truncated_ciphertext),
  + );
  + // Use the same seek target as above.
  + match truncated_reader.seek(SeekFrom::End(eof_relative_offset)) {
  + Err(e) => {
  + assert_eq!(e.kind(), io::ErrorKind::InvalidData);
  + assert_eq!(
  + &e.to_string(),
  + "Last chunk is invalid, stream might be truncated",
  + );
  + }
  + Ok(_) => panic!("This is a security issue."),
  + }
  + }
  }
  