From ef37f14d539d417a1a4506c5c09df1409700aa30 Mon Sep 17 00:00:00 2001 From: richiesams Date: Wed, 12 Jun 2013 22:06:05 -0500 Subject: ZVISION: Add xor encryption handling to ZfsArchive class --- engines/zvision/zfsArchive.cpp | 29 +++++++++++++++++++---------- engines/zvision/zfsArchive.h | 28 ++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/zvision/zfsArchive.cpp b/engines/zvision/zfsArchive.cpp index a3111d7705..59e65f1713 100644 --- a/engines/zvision/zfsArchive.cpp +++ b/engines/zvision/zfsArchive.cpp @@ -55,16 +55,17 @@ ZfsArchive::~ZfsArchive() { } void ZfsArchive::readHeaders(Common::SeekableReadStream *stream) { - ZfsHeader header; - // Don't do a straight struct cast since we can't guarantee endianness - header.magic = stream->readUint32LE(); - header.unknown1 = stream->readUint32LE(); - header.unknown2 = stream->readUint32LE(); - header.filesPerBlock = stream->readUint32LE(); - header.fileCount = stream->readUint32LE(); - header.xorKey = stream->readUint32LE(); - header.fileSectionOffset = stream->readUint32LE(); + _header.magic = stream->readUint32LE(); + _header.unknown1 = stream->readUint32LE(); + _header.maxNameLength = stream->readUint32LE(); + _header.filesPerBlock = stream->readUint32LE(); + _header.fileCount = stream->readUint32LE(); + _header.xorKey[0] = stream->readByte(); + _header.xorKey[1] = stream->readByte(); + _header.xorKey[2] = stream->readByte(); + _header.xorKey[3] = stream->readByte(); + _header.fileSectionOffset = stream->readUint32LE(); uint32 nextOffset; @@ -73,7 +74,7 @@ void ZfsArchive::readHeaders(Common::SeekableReadStream *stream) { nextOffset = stream->readUint32LE(); // Read in each entry header - for (int i = 0; i < header.filesPerBlock; i++) { + for (int i = 0; i < _header.filesPerBlock; i++) { ZfsEntryHeader entryHeader; entryHeader.name = readEntryName(stream); @@ -135,10 +136,18 @@ Common::SeekableReadStream *ZfsArchive::createReadStreamForMember(const Common:: byte* buffer = new byte[entryHeader->size]; zfsArchive.read(buffer, entryHeader->size); + // Decrypt the data in place + if (_header.xorKey != 0) + unXor(buffer, entryHeader->size, _header.xorKey); return new Common::MemoryReadStream(buffer, entryHeader->size, DisposeAfterUse::YES); } +void ZfsArchive::unXor(byte *buffer, int length, const byte *xorKey) const { + for (uint32 i = 0; i < length; i++) + buffer[i] ^= xorKey[i % 4]; +} + } // End namespace ZVision diff --git a/engines/zvision/zfsArchive.h b/engines/zvision/zfsArchive.h index 96c002f815..718b26c836 100644 --- a/engines/zvision/zfsArchive.h +++ b/engines/zvision/zfsArchive.h @@ -32,10 +32,10 @@ namespace ZVision { struct ZfsHeader { uint32 magic; uint32 unknown1; - uint32 unknown2; + uint32 maxNameLength; uint32 filesPerBlock; uint32 fileCount; - uint32 xorKey; + byte xorKey[4]; uint32 fileSectionOffset; }; @@ -85,10 +85,34 @@ public: private: const Common::String _fileName; + ZfsHeader _header; ZfsEntryHeaderMap _entryHeaders; + /** + * Parses the zfs file into file entry headers that can be used later + * to get the entry data. + * + * @param stream The contents of the zfs file + */ void readHeaders(Common::SeekableReadStream *stream); + + /** + * Entry names are contained within a 16 byte block. This reads the block + * and converts it the name to a Common::String + * + * @param stream The zfs file stream + * @return The entry file name + */ Common::String readEntryName(Common::SeekableReadStream *stream) const; + + /** + * ZFS file entries can be encrypted using XOR encoding. This method + * decodes the buffer in place using the supplied xorKey. + * + * @param buffer The data to decode + * @param length Length of buffer + */ + void unXor(byte *buffer, int length, const byte *xorKey) const; }; } // End of namespace Common -- cgit v1.2.3