From 2aea94e529d72b13e49ded016d66ab47f32cc0a2 Mon Sep 17 00:00:00 2001 From: Alexander Batischev Date: Fri, 4 Jun 2021 23:13:33 +0300 Subject: feat: do not panic if chunk nonce is unexpectedly short Fixes #119. --- src/cipher.rs | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/cipher.rs b/src/cipher.rs index 550fafd..f19dc78 100644 --- a/src/cipher.rs +++ b/src/cipher.rs @@ -78,13 +78,10 @@ impl CipherEngine { let version_len = CHUNK_V1.len(); let bytes = &bytes[version_len..]; - // Get nonce. - let nonce = &bytes[..NONCE_SIZE]; - if nonce.len() != NONCE_SIZE { - return Err(CipherError::NoNonce); - } - let nonce = GenericArray::from_slice(nonce); - let ciphertext = &bytes[NONCE_SIZE..]; + let (nonce, ciphertext) = match bytes.get(..NONCE_SIZE) { + Some(nonce) => (GenericArray::from_slice(nonce), &bytes[NONCE_SIZE..]), + None => return Err(CipherError::NoNonce), + }; let payload = Payload { msg: ciphertext, @@ -169,7 +166,7 @@ impl Nonce { mod test { use crate::chunk::DataChunk; use crate::chunkmeta::ChunkMeta; - use crate::cipher::CipherEngine; + use crate::cipher::{CipherEngine, CipherError, CHUNK_V1, NONCE_SIZE}; use crate::passwords::Passwords; #[test] @@ -197,4 +194,26 @@ mod test { let dec = cipher.decrypt_chunk(&bytes, enc.aad()).unwrap(); assert_eq!(chunk, dec); } + + #[test] + fn decrypt_errors_if_nonce_is_too_short() { + let pass = Passwords::new("our little test secret"); + let e = CipherEngine::new(&pass); + + // *Almost* a valid chunk header, except it's one byte too short + let bytes = { + let mut result = [0; CHUNK_V1.len() + NONCE_SIZE - 1]; + for (i, x) in CHUNK_V1.iter().enumerate() { + result[i] = *x; + } + result + }; + + let meta = [0; 0]; + + assert!(matches!( + e.decrypt_chunk(&bytes, &meta), + Err(CipherError::NoNonce) + )); + } } -- cgit v1.2.1