From 12260f56233000e8d77dc51d7cd402f3b95efb70 Mon Sep 17 00:00:00 2001 From: Lireer Date: Thu, 8 Oct 2020 18:25:30 +0200 Subject: [PATCH] disable crc32 checks when handling aes encrypted data --- README.md | 2 +- src/crc32.rs | 16 ++++++++++------ src/read.rs | 18 ++++++++++-------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index e489b98d..b4df15a7 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ All of these are enabled by default. MSRV ---- -Our current Minimum Supported Rust Version is **1.36.0**. When adding features, +Our current Minimum Supported Rust Version is **1.42.0**. When adding features, we will follow these guidelines: - We will always support the latest four minor Rust versions. This gives you a 6 diff --git a/src/crc32.rs b/src/crc32.rs index b351aa01..5c34f25a 100644 --- a/src/crc32.rs +++ b/src/crc32.rs @@ -10,15 +10,19 @@ pub struct Crc32Reader { inner: R, hasher: Hasher, check: u32, + /// Signals if `inner` stores aes encrypted data. + /// AE-2 encrypted data doesn't use crc and sets the value to 0. + aes_encrypted: bool, } impl Crc32Reader { /// Get a new Crc32Reader which check the inner reader against checksum. - pub fn new(inner: R, checksum: u32) -> Crc32Reader { + pub fn new(inner: R, checksum: u32, aes_encrypted: bool) -> Crc32Reader { Crc32Reader { inner, hasher: Hasher::new(), check: checksum, + aes_encrypted, } } @@ -34,7 +38,7 @@ impl Crc32Reader { impl Read for Crc32Reader { fn read(&mut self, buf: &mut [u8]) -> io::Result { let count = match self.inner.read(buf) { - Ok(0) if !buf.is_empty() && !self.check_matches() => { + Ok(0) if !buf.is_empty() && !self.check_matches() && !self.aes_encrypted => { return Err(io::Error::new(io::ErrorKind::Other, "Invalid checksum")) } Ok(n) => n, @@ -55,10 +59,10 @@ mod test { let data: &[u8] = b""; let mut buf = [0; 1]; - let mut reader = Crc32Reader::new(data, 0); + let mut reader = Crc32Reader::new(data, 0, false); assert_eq!(reader.read(&mut buf).unwrap(), 0); - let mut reader = Crc32Reader::new(data, 1); + let mut reader = Crc32Reader::new(data, 1, false); assert!(reader .read(&mut buf) .unwrap_err() @@ -71,7 +75,7 @@ mod test { let data: &[u8] = b"1234"; let mut buf = [0; 1]; - let mut reader = Crc32Reader::new(data, 0x9be3e0a3); + let mut reader = Crc32Reader::new(data, 0x9be3e0a3, false); assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.read(&mut buf).unwrap(), 1); assert_eq!(reader.read(&mut buf).unwrap(), 1); @@ -86,7 +90,7 @@ mod test { let data: &[u8] = b"1234"; let mut buf = [0; 5]; - let mut reader = Crc32Reader::new(data, 0x9be3e0a3); + let mut reader = Crc32Reader::new(data, 0x9be3e0a3, false); assert_eq!(reader.read(&mut buf[..0]).unwrap(), 0); assert_eq!(reader.read(&mut buf).unwrap(), 4); } diff --git a/src/read.rs b/src/read.rs index e1afaf03..4b60d246 100644 --- a/src/read.rs +++ b/src/read.rs @@ -1,6 +1,6 @@ //! Types for reading ZIP archives -use crate::aes::{AesReaderValid, AesReader}; +use crate::aes::{AesReader, AesReaderValid}; use crate::compression::CompressionMethod; use crate::cp437::FromCp437; use crate::crc32::Crc32Reader; @@ -205,8 +205,11 @@ fn make_reader<'a>( crc32: u32, reader: CryptoReader<'a>, ) -> ZipFileReader<'a> { + let aes_encrypted = matches!(reader, CryptoReader::Aes(_)); match compression_method { - CompressionMethod::Stored => ZipFileReader::Stored(Crc32Reader::new(reader, crc32)), + CompressionMethod::Stored => { + ZipFileReader::Stored(Crc32Reader::new(reader, crc32, aes_encrypted)) + } #[cfg(any( feature = "deflate", feature = "deflate-miniz", @@ -214,12 +217,12 @@ fn make_reader<'a>( ))] CompressionMethod::Deflated => { let deflate_reader = DeflateDecoder::new(reader); - ZipFileReader::Deflated(Crc32Reader::new(deflate_reader, crc32)) + ZipFileReader::Deflated(Crc32Reader::new(deflate_reader, crc32, aes_encrypted)) } #[cfg(feature = "bzip2")] CompressionMethod::Bzip2 => { let bzip2_reader = BzDecoder::new(reader); - ZipFileReader::Bzip2(Crc32Reader::new(bzip2_reader, crc32)) + ZipFileReader::Bzip2(Crc32Reader::new(bzip2_reader, crc32, aes_encrypted)) } _ => panic!("Compression method not supported"), } @@ -514,7 +517,7 @@ impl ZipArchive { limit_reader, password, data.aes_mode, - data.compressed_size + data.compressed_size, ) { Ok(Ok(crypto_reader)) => Ok(Ok(ZipFile { crypto_reader: Some(crypto_reader), @@ -610,13 +613,12 @@ pub(crate) fn central_header_to_zip_file( large_file: false, aes_mode: None, }; - + match parse_extra_field(&mut result) { Ok(..) | Err(ZipError::Io(..)) => {} Err(e) => return Err(e), } - - + let aes_enabled = result.compression_method == CompressionMethod::AES; if aes_enabled && result.aes_mode.is_none() { return Err(ZipError::InvalidArchive(