From c35b97c2a83bc17b14c25f1a4f62520c50042d31 Mon Sep 17 00:00:00 2001 From: brycx Date: Sat, 3 Dec 2022 14:42:25 +0100 Subject: [PATCH] chacha20: Do not copy plaintext into dst_out before we know next keystream can be reliably produced (see #308) --- src/hazardous/stream/chacha20.rs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/hazardous/stream/chacha20.rs b/src/hazardous/stream/chacha20.rs index 029fad32..6205a0a1 100644 --- a/src/hazardous/stream/chacha20.rs +++ b/src/hazardous/stream/chacha20.rs @@ -355,13 +355,29 @@ pub fn encrypt( return Err(UnknownCryptoError); } - dst_out[..plaintext.len()].copy_from_slice(plaintext); - encrypt_in_place( - secret_key, - nonce, - initial_counter, - &mut dst_out[..plaintext.len()], - ) + let mut ctx = ChaCha20::new(secret_key.unprotected_as_bytes(), nonce.as_ref(), true)?; + let mut keystream_block = Zeroizing::new([0u8; CHACHA_BLOCKSIZE]); + + for (ctr, (p_block, c_block)) in plaintext + .chunks(CHACHA_BLOCKSIZE) + .zip(dst_out.chunks_mut(CHACHA_BLOCKSIZE)) + .enumerate() + { + match initial_counter.checked_add(ctr as u32) { + Some(counter) => { + // See https://github.com/orion-rs/orion/issues/308 + ctx.next_produceable()?; + + ctx.keystream_block(counter, keystream_block.as_mut()); + xor_slices!(p_block, keystream_block.as_mut()); + c_block[..p_block.len()] + .copy_from_slice(&keystream_block.as_ref()[..p_block.len()]); + } + None => return Err(UnknownCryptoError), + } + } + + Ok(()) } #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]