disable crc32 checks when handling aes encrypted data

This commit is contained in:
Lireer 2020-10-08 18:25:30 +02:00 committed by Lireer
parent 852ab625fb
commit 12260f5623
3 changed files with 21 additions and 15 deletions

View file

@ -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

View file

@ -10,15 +10,19 @@ pub struct Crc32Reader<R> {
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<R> Crc32Reader<R> {
/// Get a new Crc32Reader which check the inner reader against checksum.
pub fn new(inner: R, checksum: u32) -> Crc32Reader<R> {
pub fn new(inner: R, checksum: u32, aes_encrypted: bool) -> Crc32Reader<R> {
Crc32Reader {
inner,
hasher: Hasher::new(),
check: checksum,
aes_encrypted,
}
}
@ -34,7 +38,7 @@ impl<R> Crc32Reader<R> {
impl<R: Read> Read for Crc32Reader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
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);
}

View file

@ -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<R: Read + io::Seek> ZipArchive<R> {
limit_reader,
password,
data.aes_mode,
data.compressed_size
data.compressed_size,
) {
Ok(Ok(crypto_reader)) => Ok(Ok(ZipFile {
crypto_reader: Some(crypto_reader),
@ -616,7 +619,6 @@ pub(crate) fn central_header_to_zip_file<R: Read + io::Seek>(
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(