-
Notifications
You must be signed in to change notification settings - Fork 67
Closed as not planned
Description
Off by one error: remaining_blocks() restricts the maximum number of blocks to u32::MAX when 0 is a valid block, raising the maximum number of blocks to u32::MAX + 1 or 1 << 32. This test passed, proving that there are 64 unusable bytes in the keystream:
macro_rules! impl_chacha20_potential_counter_issue {
($name:ident, $num_blocks:literal) => {
#[test]
fn $name() {
let mut cipher = ChaCha20::new(&KEY.into(), &IV.into());
let mut first_4_blocks = [0u8; 256];
assert_eq!(cipher.current_pos::<u64>(), 0);
cipher.apply_keystream(&mut first_4_blocks);
let mut buf_1 = [0u8; $num_blocks * 64];
let mut buf_2 = [0u8; $num_blocks * 64 + 1];
// seek to end of keystream
let pos = (1 << 32) * 64 - $num_blocks * 64 - 64;
cipher.try_seek(pos).unwrap();
assert_eq!(cipher.current_pos::<u64>(), pos);
// overshoot keystream length
let applied_keystream = cipher.try_apply_keystream(&mut buf_2);
assert_eq!(applied_keystream.is_err(), true);
// exhaust keystream
cipher.apply_keystream(&mut buf_1);
// seek to beginning and check if the first block is the same as before
cipher.seek(0);
assert_eq!(cipher.current_pos::<u64>(), 0);
cipher.apply_keystream(&mut first_4_blocks);
// if this assert fails, exhausting the keystream increments
// state[13], resulting in a different keystream when it
// should be the same
assert_eq!(first_4_blocks, [0u8; 256]);
}
};
}Because this test passes (specifically assert_eq!(applied_keystream.is_err()) and the pos value and size of the buffers), it proves that the seek_pos has to be 64 bytes less than expected to reach the end of the supposed keystream.
I ran into this error when working the counter, but it is easily fixable and has already been fixed in the PR
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels