diff --git a/rustcryptfs-fuse/src/encrypted_filesystem.rs b/rustcryptfs-fuse/src/encrypted_filesystem.rs index 7f5f5e1..7179368 100644 --- a/rustcryptfs-fuse/src/encrypted_filesystem.rs +++ b/rustcryptfs-fuse/src/encrypted_filesystem.rs @@ -240,7 +240,7 @@ impl EncryptedFs { { let n = file.read(&mut buf)?; - let res = decoder.decrypt_block(&buf[..n], block_index, id)?; + let res = decoder.decrypt_block(&mut buf[..n], block_index, id)?; let seek = (offset as u64 - block_index * 4096) as usize; buffer.extend_from_slice(&res[seek..]); @@ -257,7 +257,7 @@ impl EncryptedFs { break; } - let res = decoder.decrypt_block(&buf[..n], block_index, id)?; + let res = decoder.decrypt_block(&mut buf[..n], block_index, id)?; let size = res.len().min(rem); diff --git a/rustcryptfs-lib/src/content/mod.rs b/rustcryptfs-lib/src/content/mod.rs index 561c255..366b81b 100644 --- a/rustcryptfs-lib/src/content/mod.rs +++ b/rustcryptfs-lib/src/content/mod.rs @@ -1,7 +1,7 @@ //! Utilities for file encryption. use aes_gcm::{aead::generic_array::GenericArray, aes::Aes256, AeadInPlace, AesGcm, NewAead}; -use cipher::consts::{U16, U32}; +use cipher::consts::U16; use hkdf::Hkdf; mod error; @@ -12,8 +12,8 @@ type Aes256Gcm = AesGcm; /// ContentEnc implement all methods related to file encryption. pub struct ContentEnc { - key: GenericArray, iv_len: usize, + cipher: Aes256Gcm, } impl ContentEnc { @@ -24,56 +24,47 @@ impl ContentEnc { hdkf.expand(b"AES-GCM file content encryption", &mut key)?; Ok(Self { - key: GenericArray::from(key), iv_len: iv_len as usize, + cipher: Aes256Gcm::new(&GenericArray::from(key)), }) } /// Decrypt a encrypted block of len (iv_len + decrypted_block_size + iv_len), with the block number and the file id. - pub fn decrypt_block( + /// The content of block is replaced with the plain text, in form of iv + plaintext + tag. + pub fn decrypt_block<'a>( &self, - block: &[u8], + block: &'a mut [u8], block_number: u64, file_id: Option<&[u8]>, - ) -> Result, ContentCipherError> { - // TODO NOT BOX + ) -> Result<&'a [u8], ContentCipherError> { if block.is_empty() { - return Ok(block.into()); - } - - if block.iter().all(|f| *f == 0) { - todo!("black hole") - } - - if block.len() < self.iv_len { + return Ok(block); + } else if block.iter().all(|f| *f == 0) { + return Ok(&block[0..block.len() - self.iv_len * 2]); + } else if block.len() < self.iv_len * 2 { return Err(ContentCipherError::BlockTooShort()); } - let nonce = &block[..self.iv_len]; - let tag = &block[block.len() - self.iv_len..]; - let ciphertext = &block[self.iv_len..block.len() - self.iv_len]; + let (nonce, other) = block.split_at_mut(self.iv_len); + let (ciphertext, tag) = other.split_at_mut(other.len() - self.iv_len); if nonce.iter().all(|f| *f == 0) { return Err(ContentCipherError::AllZeroNonce()); } - let mut buf = Vec::from(ciphertext); - let mut aad = Vec::from(block_number.to_be_bytes()); if let Some(file_id) = file_id { aad.extend(file_id); } - let aes = Aes256Gcm::new(&self.key); - - aes.decrypt_in_place_detached( + self.cipher.decrypt_in_place_detached( GenericArray::from_slice(nonce), &aad, - &mut buf, + ciphertext, GenericArray::from_slice(tag), )?; - Ok(buf.to_vec()) + Ok(ciphertext) } /// Return the decrypted size of a file, based on the encrypted size. @@ -93,7 +84,7 @@ impl ContentEnc { mod test { use std::io::{Cursor, Read}; - use sha2::{Sha256, Digest}; + use sha2::{Digest, Sha256}; use super::ContentEnc; @@ -112,37 +103,41 @@ mod test { #[test] fn test_decrypt_empty_file() { - let content = include_bytes!( - concat!(env!("CARGO_MANIFEST_DIR"), - "/../test-data/test.bin")); + let content = include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../test-data/test.bin" + )); let master_key = base64::decode("9gtUW9XiiefEgEXEkbONI6rnUsd2yh5UZZLG0V8Bxgk=").unwrap(); let file_cipher = ContentEnc::new(&master_key, 16).unwrap(); - let res = file_cipher.decrypt_block(&[], 1, None).expect("Failed to decrypt empty block"); + let res = file_cipher + .decrypt_block(&mut [], 1, None) + .expect("Failed to decrypt empty block"); assert_eq!(res, Vec::::new()); - let mut reader= Cursor::new(content); - - let mut hasher = Sha256::new(); + let mut reader = Cursor::new(content); + let mut hasher = Sha256::new(); let mut buf = [0u8; 18]; let n = reader.read(&mut buf).unwrap(); let id = if n < 18 { None } else { Some(&buf[2..]) }; - + let mut buf = [0u8; 4096 + 32]; - + let mut block_index = 0; loop { let n = reader.read(&mut buf).unwrap(); - let res = file_cipher.decrypt_block(&buf[..n], block_index, id).unwrap(); - + let res = file_cipher + .decrypt_block(&mut buf[..n], block_index, id) + .unwrap(); + hasher.update(&res); if res.is_empty() { break; } - + block_index += 1; } diff --git a/rustcryptfs/src/main.rs b/rustcryptfs/src/main.rs index f196bfc..edd9845 100644 --- a/rustcryptfs/src/main.rs +++ b/rustcryptfs/src/main.rs @@ -105,9 +105,9 @@ fn decrypt_file(c: &DecryptCommand) -> anyhow::Result<()> { let mut block_index = 0; loop { let n = file.read(&mut buf)?; - let res = enc.decrypt_block(&buf[..n], block_index, id)?; + let res = enc.decrypt_block(&mut buf[..n], block_index, id)?; - stdout.write_all(&res)?; + stdout.write_all(res)?; if res.is_empty() { break;