From 4ce93ff4ff60b21bf0bbb7ccc2b1900d0f4435ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C5=93ur?= Date: Mon, 28 Oct 2024 18:08:25 +0100 Subject: [PATCH] Updating to minizip-ng 4.0.7 (#724) * Updating to minizip-ng 4.0.7 * Adding HAVE_ICONV --- .../ObjectiveCExampleTests/ProgressDelegate.h | 3 +- .../ObjectiveCExampleTests/ProgressDelegate.m | 2 + .../SSZipArchiveTests.m | 8 + Example/Podfile.lock | 4 +- Package.swift | 3 +- README.md | 2 +- Release-Instructions.md | 14 +- SSZipArchive.podspec | 4 +- SSZipArchive/SSZipCommon.h | 65 +-- SSZipArchive/minizip/mz.h | 15 +- SSZipArchive/minizip/mz_compat.c | 136 ++++-- SSZipArchive/minizip/mz_compat.h | 67 ++- SSZipArchive/minizip/mz_crypt.c | 12 +- SSZipArchive/minizip/mz_crypt.h | 24 +- SSZipArchive/minizip/mz_crypt_apple.c | 346 +++++++------ SSZipArchive/minizip/mz_os.c | 14 +- SSZipArchive/minizip/mz_os.h | 4 +- SSZipArchive/minizip/mz_os_posix.c | 14 +- SSZipArchive/minizip/mz_strm.c | 15 +- SSZipArchive/minizip/mz_strm.h | 6 +- SSZipArchive/minizip/mz_strm_buf.c | 9 +- SSZipArchive/minizip/mz_strm_buf.h | 2 +- SSZipArchive/minizip/mz_strm_mem.c | 9 +- SSZipArchive/minizip/mz_strm_mem.h | 2 +- SSZipArchive/minizip/mz_strm_os.h | 2 +- SSZipArchive/minizip/mz_strm_os_posix.c | 9 +- SSZipArchive/minizip/mz_strm_pkcrypt.c | 26 +- SSZipArchive/minizip/mz_strm_pkcrypt.h | 6 +- SSZipArchive/minizip/mz_strm_split.c | 19 +- SSZipArchive/minizip/mz_strm_split.h | 2 +- SSZipArchive/minizip/mz_strm_wzaes.c | 57 ++- SSZipArchive/minizip/mz_strm_wzaes.h | 4 +- SSZipArchive/minizip/mz_strm_zlib.c | 16 +- SSZipArchive/minizip/mz_strm_zlib.h | 2 +- SSZipArchive/minizip/mz_zip.c | 107 ++-- SSZipArchive/minizip/mz_zip.h | 4 +- SSZipArchive/minizip/mz_zip_rw.c | 460 ++++++++---------- SSZipArchive/minizip/mz_zip_rw.h | 13 +- ZipArchive.xcodeproj/project.pbxproj | 2 + 39 files changed, 797 insertions(+), 712 deletions(-) diff --git a/Example/ObjectiveCExampleTests/ProgressDelegate.h b/Example/ObjectiveCExampleTests/ProgressDelegate.h index c12611c..3f8541e 100644 --- a/Example/ObjectiveCExampleTests/ProgressDelegate.h +++ b/Example/ObjectiveCExampleTests/ProgressDelegate.h @@ -17,7 +17,8 @@ @interface ProgressDelegate : NSObject { @public - NSMutableArray *progressEvents; + NSMutableArray *fileInfos; + NSMutableArray *progressEvents; } @end diff --git a/Example/ObjectiveCExampleTests/ProgressDelegate.m b/Example/ObjectiveCExampleTests/ProgressDelegate.m index 07abef2..5fa9f8a 100644 --- a/Example/ObjectiveCExampleTests/ProgressDelegate.m +++ b/Example/ObjectiveCExampleTests/ProgressDelegate.m @@ -12,6 +12,7 @@ - (instancetype)init { self = super.init; + fileInfos = [NSMutableArray array]; progressEvents = [NSMutableArray array]; return self; } @@ -27,6 +28,7 @@ - (BOOL)zipArchiveShouldUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo { NSLog(@"*** zipArchiveShouldUnzipFileAtIndex: `%d` totalFiles: `%d` archivePath: `%@` fileInfo:", (int)fileIndex, (int)totalFiles, archivePath); + [fileInfos addObject:[NSValue value:&fileInfo withObjCType:@encode(unz_file_info)]]; return YES; } diff --git a/Example/ObjectiveCExampleTests/SSZipArchiveTests.m b/Example/ObjectiveCExampleTests/SSZipArchiveTests.m index 9d407b2..1e97baa 100644 --- a/Example/ObjectiveCExampleTests/SSZipArchiveTests.m +++ b/Example/ObjectiveCExampleTests/SSZipArchiveTests.m @@ -221,6 +221,14 @@ int twentyMB = 20 * 1024 * 1024; XCTAssertTrue(619 == [delegate->progressEvents[1] intValue]); XCTAssertTrue(1114 == [delegate->progressEvents[2] intValue]); XCTAssertTrue(1436 == [delegate->progressEvents[3] intValue]); + + XCTAssertTrue(2 == [delegate->fileInfos count], @"Expected 2 files"); + unz_file_info info; + [delegate->fileInfos[0] getValue:&info]; + // This test is to ensure that ZipArchive 2.x keeps support of `dos_date` instead of `dosDate`, despite the legacy name at: + // https://github.com/madler/zlib/blame/643e17b7498d12ab8d15565662880579692f769d/contrib/minizip/unzip.h#L138 + // In ZipArchive 3, we should hide this outdated structure from public. + XCTAssertNotEqual(info.dos_date, 0); } diff --git a/Example/Podfile.lock b/Example/Podfile.lock index d78b212..da1566a 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - SSZipArchive (2.6.0) + - SSZipArchive (2.6.1) DEPENDENCIES: - SSZipArchive (from `..`) @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :path: ".." SPEC CHECKSUMS: - SSZipArchive: 8a6ee5677c8e304bebc109e39cf0da91ccef22ea + SSZipArchive: 9aa2d1327379f342c3ec700147b40387c1d8bd21 PODFILE CHECKSUM: f72aa12c216b9028a1e05f38d3c62c3f6f602c06 diff --git a/Package.swift b/Package.swift index 2764d45..e461c3d 100644 --- a/Package.swift +++ b/Package.swift @@ -23,7 +23,8 @@ let package = Package( resources: [ .process("Supporting Files/PrivacyInfo.xcprivacy")], cSettings: [ - .define("HAVE_ARC4RANDOM_BUF"), + .define("HAVE_ARC4RANDOM_BUF"), + .define("HAVE_ICONV"), .define("HAVE_INTTYPES_H"), .define("HAVE_PKCRYPT"), .define("HAVE_STDINT_H"), diff --git a/README.md b/README.md index d62550a..d0bd4a6 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ We do not release a Carthage pre-built package. Developers are encouraged to bui 1. Add the `SSZipArchive` and `minizip` folders to your project. 2. Add the `libz` and `libiconv` libraries to your target. 3. Add the `Security` framework to your target. -4. Add the following GCC_PREPROCESSOR_DEFINITIONS: `HAVE_ARC4RANDOM_BUF HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB ZLIB_COMPAT $(inherited)`. +4. Add the following GCC_PREPROCESSOR_DEFINITIONS: `HAVE_ARC4RANDOM_BUF HAVE_ICONV HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB ZLIB_COMPAT $(inherited)`. SSZipArchive requires ARC. diff --git a/Release-Instructions.md b/Release-Instructions.md index d2d43a8..dd30114 100644 --- a/Release-Instructions.md +++ b/Release-Instructions.md @@ -30,23 +30,19 @@ The following steps should be taken by project maintainers when they update mini 2. Have cmake: `brew install cmake` 3. Run cmake on minizip repo with our desired configuration: -`cmake . -DMZ_BZIP2=OFF -DMZ_LZMA=OFF -DMZ_ZLIB=ON -DMZ_LIBCOMP=OFF` +`cmake . -DMZ_BZIP2=OFF -DMZ_LIBCOMP=OFF -DMZ_LZMA=OFF -DMZ_OPENSSL=OFF -DMZ_ZLIB=ON -DMZ_ZSTD=OFF` 4. Look at the file `./CMakeFiles/minizip.dir/DependInfo.cmake` it will give you the following information: - The list of C files that we need to include. 5. Look at the file `./CMakeFiles/minizip.dir/flags.make` it will give you the following information: +- The list of compiler flags that we need to include (we have to either include zlib-ng or use ZLIB_COMPAT) -- The list of compiler flags that we need to include (as of minizip 3.0.5 we have to include either zlib-ng OR ZLIB_COMPAT) - -Note: These should not be changed unless you have issues compiling or we bump the min os versions. - -HAVE_ARC4RANDOM_BUF HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB ZLIB_COMPAT - -With the exception of the last two: "MZ_ZIP_SIGNING" "_POSIX_C_SOURCE=200112L" +HAVE_ARC4RANDOM_BUF HAVE_ICONV HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB ZLIB_COMPAT +Ignoring the ones starting with an underscore, like: "_BSD_SOURCE" "_DARWIN_C_SOURCE" "_DEFAULT_SOURCE" "_POSIX_C_SOURCE=200809L" 6. Set those flags in SSZipArchive.podspec (for CocoaPods) and in ZipArchive.xcodeproj (for Carthage) 7. Replace the .h and .c files with the latest ones, except for `mz_compat.h`, which is customized to expose some struct in SSZipCommon.h and to provide support for optional aes. -Note: we can also use `cmake -G Xcode . -DMZ_BZIP2=OFF -DMZ_LZMA=OFF -DMZ_ZLIB=ON -DMZ_LIBCOMP=OFF` to get the list of files to include in an xcodeproj of its own, from where we can remove unneeded `zip.h` and `unzip.h`. +Note: we can also use `cmake -G Xcode . -DMZ_BZIP2=OFF -DMZ_LIBCOMP=OFF -DMZ_LZMA=OFF -DMZ_OPENSSL=OFF -DMZ_ZLIB=ON -DMZ_ZSTD=OFF` to get the list of files to include in an xcodeproj of its own, from where we can remove unneeded `zip.h` and `unzip.h`. diff --git a/SSZipArchive.podspec b/SSZipArchive.podspec index 78a2f7e..e52ef24 100644 --- a/SSZipArchive.podspec +++ b/SSZipArchive.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'SSZipArchive' - s.version = '2.6.0' + s.version = '2.6.1' s.summary = 'Utility class for zipping and unzipping files on iOS, tvOS, visionOS, watchOS, and macOS.' s.description = 'SSZipArchive is a simple utility class for zipping and unzipping files on iOS, tvOS, visionOS, watchOS, and macOS. It supports AES and PKWARE encryption.' s.homepage = 'https://github.com/ZipArchive/ZipArchive' @@ -18,5 +18,5 @@ Pod::Spec.new do |s| s.libraries = 'z', 'iconv' s.framework = 'Security' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', - 'GCC_PREPROCESSOR_DEFINITIONS' => 'HAVE_ARC4RANDOM_BUF HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB ZLIB_COMPAT' } + 'GCC_PREPROCESSOR_DEFINITIONS' => 'HAVE_ARC4RANDOM_BUF HAVE_ICONV HAVE_INTTYPES_H HAVE_PKCRYPT HAVE_STDINT_H HAVE_WZAES HAVE_ZLIB ZLIB_COMPAT' } end diff --git a/SSZipArchive/SSZipCommon.h b/SSZipArchive/SSZipCommon.h index 6c77573..491a0b6 100644 --- a/SSZipArchive/SSZipCommon.h +++ b/SSZipArchive/SSZipCommon.h @@ -5,65 +5,36 @@ /* unz_global_info structure contain global data about the ZIPfile These data comes from the end of central dir */ -typedef struct unz_global_info64_s -{ - uint64_t number_entry; /* total number of entries in the central dir on this disk */ - uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */ - uint16_t size_comment; /* size of the global comment of the zipfile */ -} unz_global_info64; - typedef struct unz_global_info_s { - uint32_t number_entry; /* total number of entries in the central dir on this disk */ + unsigned long number_entry; /* total number of entries in the central dir on this disk */ + unsigned long size_comment; /* size of the global comment of the zipfile */ uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */ - uint16_t size_comment; /* size of the global comment of the zipfile */ } unz_global_info; /* unz_file_info contain information about a file in the zipfile */ /* https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT */ -typedef struct unz_file_info64_s -{ - uint16_t version; /* version made by 2 bytes */ - uint16_t version_needed; /* version needed to extract 2 bytes */ - uint16_t flag; /* general purpose bit flag 2 bytes */ - uint16_t compression_method; /* compression method 2 bytes */ - uint32_t dos_date; /* last mod file date in Dos fmt 4 bytes */ - struct tm tmu_date; - uint32_t crc; /* crc-32 4 bytes */ - uint64_t compressed_size; /* compressed size 8 bytes */ - uint64_t uncompressed_size; /* uncompressed size 8 bytes */ - uint16_t size_filename; /* filename length 2 bytes */ - uint16_t size_file_extra; /* extra field length 2 bytes */ - uint16_t size_file_comment; /* file comment length 2 bytes */ - - uint32_t disk_num_start; /* disk number start 4 bytes */ - uint16_t internal_fa; /* internal file attributes 2 bytes */ - uint32_t external_fa; /* external file attributes 4 bytes */ - - uint64_t disk_offset; - - uint16_t size_file_extra_internal; -} unz_file_info64; typedef struct unz_file_info_s { - uint16_t version; /* version made by 2 bytes */ - uint16_t version_needed; /* version needed to extract 2 bytes */ - uint16_t flag; /* general purpose bit flag 2 bytes */ - uint16_t compression_method; /* compression method 2 bytes */ - uint32_t dos_date; /* last mod file date in Dos fmt 4 bytes */ - struct tm tmu_date; - uint32_t crc; /* crc-32 4 bytes */ - uint32_t compressed_size; /* compressed size 4 bytes */ - uint32_t uncompressed_size; /* uncompressed size 4 bytes */ - uint16_t size_filename; /* filename length 2 bytes */ - uint16_t size_file_extra; /* extra field length 2 bytes */ - uint16_t size_file_comment; /* file comment length 2 bytes */ + unsigned long version; /* version made by 2 bytes */ + unsigned long version_needed; /* version needed to extract 2 bytes */ + unsigned long flag; /* general purpose bit flag 2 bytes */ + unsigned long compression_method; /* compression method 2 bytes */ + unsigned long dos_date; /* last mod file date in Dos fmt 4 bytes */ + unsigned long crc; /* crc-32 4 bytes */ + unsigned long compressed_size; /* compressed size 4 bytes */ + unsigned long uncompressed_size; /* uncompressed size 4 bytes */ + unsigned long size_filename; /* filename length 2 bytes */ + unsigned long size_file_extra; /* extra field length 2 bytes */ + unsigned long size_file_comment; /* file comment length 2 bytes */ - uint16_t disk_num_start; /* disk number start 2 bytes */ - uint16_t internal_fa; /* internal file attributes 2 bytes */ - uint32_t external_fa; /* external file attributes 4 bytes */ + unsigned long disk_num_start; /* disk number start 2 bytes */ + unsigned long internal_fa; /* internal file attributes 2 bytes */ + unsigned long external_fa; /* external file attributes 4 bytes */ + + struct tm tmu_date; uint64_t disk_offset; } unz_file_info; diff --git a/SSZipArchive/minizip/mz.h b/SSZipArchive/minizip/mz.h index 769a7b6..ca48bd2 100644 --- a/SSZipArchive/minizip/mz.h +++ b/SSZipArchive/minizip/mz.h @@ -14,8 +14,8 @@ /***************************************************************************/ /* MZ_VERSION */ -#define MZ_VERSION ("3.0.10") -#define MZ_VERSION_BUILD (03000a) +#define MZ_VERSION ("4.0.7") +#define MZ_VERSION_BUILD (0x040007) /* MZ_ERROR */ #define MZ_OK (0) /* zlib */ @@ -112,13 +112,14 @@ /* MZ_AES */ #define MZ_AES_VERSION (1) -#define MZ_AES_ENCRYPTION_MODE_128 (0x01) -#define MZ_AES_ENCRYPTION_MODE_192 (0x02) -#define MZ_AES_ENCRYPTION_MODE_256 (0x03) -#define MZ_AES_KEY_LENGTH(MODE) (8 * (MODE & 3) + 8) +#define MZ_AES_MODE_ECB (0) +#define MZ_AES_MODE_CBC (1) +#define MZ_AES_MODE_GCM (2) +#define MZ_AES_STRENGTH_128 (1) +#define MZ_AES_STRENGTH_192 (2) +#define MZ_AES_STRENGTH_256 (3) #define MZ_AES_KEY_LENGTH_MAX (32) #define MZ_AES_BLOCK_SIZE (16) -#define MZ_AES_HEADER_SIZE(MODE) ((4 * (MODE & 3) + 4) + 2) #define MZ_AES_FOOTER_SIZE (10) /* MZ_HASH */ diff --git a/SSZipArchive/minizip/mz_compat.c b/SSZipArchive/minizip/mz_compat.c index 9f251d5..334dd51 100644 --- a/SSZipArchive/minizip/mz_compat.c +++ b/SSZipArchive/minizip/mz_compat.c @@ -54,7 +54,7 @@ static int64_t mz_stream_ioapi_tell(void *stream); static int32_t mz_stream_ioapi_seek(void *stream, int64_t offset, int32_t origin); static int32_t mz_stream_ioapi_close(void *stream); static int32_t mz_stream_ioapi_error(void *stream); -static void *mz_stream_ioapi_create(void **stream); +static void *mz_stream_ioapi_create(void); static void mz_stream_ioapi_delete(void **stream); /***************************************************************************/ @@ -236,15 +236,10 @@ static int32_t mz_stream_ioapi_set_filefunc64(void *stream, zlib_filefunc64_def return MZ_OK; } -static void *mz_stream_ioapi_create(void **stream) { - mz_stream_ioapi *ioapi = NULL; - - ioapi = (mz_stream_ioapi *)calloc(1, sizeof(mz_stream_ioapi)); +static void *mz_stream_ioapi_create(void) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)calloc(1, sizeof(mz_stream_ioapi)); if (ioapi) ioapi->stream.vtbl = &mz_stream_ioapi_vtbl; - if (stream) - *stream = ioapi; - return ioapi; } @@ -336,17 +331,20 @@ zipFile zipOpen2(const char *path, int append, const char **globalcomment, if (pzlib_filefunc_def) { if (pzlib_filefunc_def->zopen_file) { - if (!mz_stream_ioapi_create(&stream)) + stream = mz_stream_ioapi_create(); + if (!stream) return NULL; mz_stream_ioapi_set_filefunc(stream, pzlib_filefunc_def); } else if (pzlib_filefunc_def->opaque) { - if (!mz_stream_create(&stream, (mz_stream_vtbl *)pzlib_filefunc_def->opaque)) + stream = mz_stream_create((mz_stream_vtbl *)pzlib_filefunc_def->opaque); + if (!stream) return NULL; } } if (!stream) { - if (!mz_stream_os_create(&stream)) + stream = mz_stream_os_create(); + if (!stream) return NULL; } @@ -373,17 +371,20 @@ zipFile zipOpen2_64(const void *path, int append, const char **globalcomment, if (pzlib_filefunc_def) { if (pzlib_filefunc_def->zopen64_file) { - if (!mz_stream_ioapi_create(&stream)) + stream = mz_stream_ioapi_create(); + if (!stream) return NULL; mz_stream_ioapi_set_filefunc64(stream, pzlib_filefunc_def); } else if (pzlib_filefunc_def->opaque) { - if (!mz_stream_create(&stream, (mz_stream_vtbl *)pzlib_filefunc_def->opaque)) + stream = mz_stream_create((mz_stream_vtbl *)pzlib_filefunc_def->opaque); + if (!stream) return NULL; } } if (!stream) { - if (!mz_stream_os_create(&stream)) + stream = mz_stream_os_create(); + if (!stream) return NULL; } @@ -408,7 +409,10 @@ zipFile zipOpen_MZ(void *stream, int append, const char **globalcomment) { int32_t mode = zipConvertAppendToStreamMode(append); void *handle = NULL; - mz_zip_create(&handle); + handle = mz_zip_create(); + if (!handle) + return NULL; + err = mz_zip_open(handle, stream, mode); if (err != MZ_OK) { @@ -462,6 +466,12 @@ int zipOpenNewFileInZip5(zipFile file, const char *filename, const zip_fileinfo if (!compat) return ZIP_PARAMERROR; + /* The filename and comment length must fit in 16 bits. */ + if (filename && strlen(filename) > 0xffff) + return ZIP_PARAMERROR; + if (comment && strlen(comment) > 0xffff) + return ZIP_PARAMERROR; + memset(&file_info, 0, sizeof(file_info)); if (zipfi) { @@ -473,8 +483,8 @@ int zipOpenNewFileInZip5(zipFile file, const char *filename, const zip_fileinfo dos_date = mz_zip_tm_to_dosdate(&zipfi->tmz_date); file_info.modified_date = mz_zip_dosdate_to_time_t(dos_date); - file_info.external_fa = zipfi->external_fa; - file_info.internal_fa = zipfi->internal_fa; + file_info.external_fa = (uint32_t)zipfi->external_fa; + file_info.internal_fa = (uint16_t)zipfi->internal_fa; } if (!filename) @@ -568,6 +578,14 @@ int zipOpenNewFileInZip(zipFile file, const char *filename, const zip_fileinfo * extrafield_global, size_extrafield_global, comment, compression_method, level, 0); } +int zipOpenNewFileInZip64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global, + uint16_t size_extrafield_global, const char *comment, int compression_method, int level, + int zip64) { + return zipOpenNewFileInZip2_64(file, filename, zipfi, extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, comment, compression_method, level, 0, zip64); +} + int zipOpenNewFileInZip_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, int compression_method, int level, @@ -587,15 +605,15 @@ int zipWriteInFileInZip(zipFile file, const void *buf, uint32_t len) { return ZIP_OK; } -int zipCloseFileInZipRaw(zipFile file, unsigned long uncompressed_size, uint32_t crc32) { +int zipCloseFileInZipRaw(zipFile file, unsigned long uncompressed_size, unsigned long crc32) { return zipCloseFileInZipRaw64(file, uncompressed_size, crc32); } -int zipCloseFileInZipRaw64(zipFile file, uint64_t uncompressed_size, uint32_t crc32) { +int zipCloseFileInZipRaw64(zipFile file, uint64_t uncompressed_size, unsigned long crc32) { mz_compat *compat = (mz_compat *)file; if (!compat) return ZIP_PARAMERROR; - return mz_zip_entry_close_raw(compat->handle, (int64_t)uncompressed_size, crc32); + return mz_zip_entry_close_raw(compat->handle, (int64_t)uncompressed_size, (uint32_t)crc32); } int zipCloseFileInZip(zipFile file) { @@ -675,17 +693,20 @@ unzFile unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def) { if (pzlib_filefunc_def) { if (pzlib_filefunc_def->zopen_file) { - if (!mz_stream_ioapi_create(&stream)) + stream = mz_stream_ioapi_create(); + if (!stream) return NULL; mz_stream_ioapi_set_filefunc(stream, pzlib_filefunc_def); } else if (pzlib_filefunc_def->opaque) { - if (!mz_stream_create(&stream, (mz_stream_vtbl *)pzlib_filefunc_def->opaque)) + stream = mz_stream_create((mz_stream_vtbl *)pzlib_filefunc_def->opaque); + if (!stream) return NULL; } } if (!stream) { - if (!mz_stream_os_create(&stream)) + stream = mz_stream_os_create(); + if (!stream) return NULL; } @@ -709,17 +730,20 @@ unzFile unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def) { if (pzlib_filefunc_def) { if (pzlib_filefunc_def->zopen64_file) { - if (!mz_stream_ioapi_create(&stream)) + stream = mz_stream_ioapi_create(); + if (!stream) return NULL; mz_stream_ioapi_set_filefunc64(stream, pzlib_filefunc_def); } else if (pzlib_filefunc_def->opaque) { - if (!mz_stream_create(&stream, (mz_stream_vtbl *)pzlib_filefunc_def->opaque)) + stream = mz_stream_create((mz_stream_vtbl *)pzlib_filefunc_def->opaque); + if (!stream) return NULL; } } if (!stream) { - if (!mz_stream_os_create(&stream)) + stream = mz_stream_os_create(); + if (!stream) return NULL; } @@ -756,9 +780,11 @@ unzFile unzOpen_MZ(void *stream) { int32_t err = MZ_OK; void *handle = NULL; - mz_zip_create(&handle); - err = mz_zip_open(handle, stream, MZ_OPEN_MODE_READ); + handle = mz_zip_create(); + if (!handle) + return NULL; + err = mz_zip_open(handle, stream, MZ_OPEN_MODE_READ); if (err != MZ_OK) { mz_zip_delete(&handle); return NULL; @@ -964,6 +990,8 @@ int unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filenam pfile_info->flag = file_info->flag; pfile_info->compression_method = file_info->compression_method; pfile_info->mz_dos_date = mz_zip_time_t_to_dos_date(file_info->modified_date); + // [ZipArchive] disabled for performances: we don't need the tmu_date field because we already set the mz_dos_date field: + // https://github.com/madler/zlib/blob/643e17b7498d12ab8d15565662880579692f769d/contrib/minizip/zip.h#L102 //mz_zip_time_t_to_tm(file_info->modified_date, &pfile_info->tmu_date); //pfile_info->tmu_date.tm_year += 1900; pfile_info->crc = file_info->crc; @@ -1025,6 +1053,8 @@ int unzGetCurrentFileInfo64(unzFile file, unz_file_info64 * pfile_info, char *fi pfile_info->flag = file_info->flag; pfile_info->compression_method = file_info->compression_method; pfile_info->mz_dos_date = mz_zip_time_t_to_dos_date(file_info->modified_date); + // [ZipArchive] disabled for performances: we don't need the tmu_date field because we already set the mz_dos_date field: + // https://github.com/madler/zlib/blob/643e17b7498d12ab8d15565662880579692f769d/contrib/minizip/zip.h#L102 //mz_zip_time_t_to_tm(file_info->modified_date, &pfile_info->tmu_date); //pfile_info->tmu_date.tm_year += 1900; pfile_info->crc = file_info->crc; @@ -1084,12 +1114,56 @@ int unzGoToNextFile(unzFile file) { return err; } -int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func) { +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION < 110 +#ifdef WIN32 +# define UNZ_DEFAULT_IGNORE_CASE 1 +#else +# define UNZ_DEFAULT_IGNORE_CASE 0 +#endif + +int unzLocateFile(unzFile file, const char *filename, unzFileNameCase filename_case) { mz_compat *compat = (mz_compat *)file; mz_zip_file *file_info = NULL; uint64_t preserve_index = 0; int32_t err = MZ_OK; int32_t result = 0; + uint8_t ignore_case = UNZ_DEFAULT_IGNORE_CASE; + + if (!compat) + return UNZ_PARAMERROR; + + if (filename_case == 1) { + ignore_case = 0; + } else if (filename_case > 1) { + ignore_case = 1; + } + + preserve_index = compat->entry_index; + + err = mz_zip_goto_first_entry(compat->handle); + while (err == MZ_OK) { + err = mz_zip_entry_get_info(compat->handle, &file_info); + if (err != MZ_OK) + break; + + result = mz_path_compare_wc(filename, file_info->filename, !ignore_case); + + if (result == 0) + return MZ_OK; + + err = mz_zip_goto_next_entry(compat->handle); + } + + compat->entry_index = preserve_index; + return err; +} +#else +int unzLocateFile(unzFile file, const char* filename, unzFileNameComparer filename_compare_func) { + mz_compat* compat = (mz_compat*)file; + mz_zip_file* file_info = NULL; + uint64_t preserve_index = 0; + int32_t err = MZ_OK; + int32_t result = 0; if (!compat) return UNZ_PARAMERROR; @@ -1104,7 +1178,8 @@ int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filena if ((intptr_t)filename_compare_func > 2) { result = filename_compare_func(file, filename, file_info->filename); - } else { + } + else { int32_t case_sensitive = (int32_t)(intptr_t)filename_compare_func; result = mz_path_compare_wc(filename, file_info->filename, !case_sensitive); } @@ -1118,6 +1193,7 @@ int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filena compat->entry_index = preserve_index; return err; } +#endif /***************************************************************************/ diff --git a/SSZipArchive/minizip/mz_compat.h b/SSZipArchive/minizip/mz_compat.h index 6192166..824949d 100644 --- a/SSZipArchive/minizip/mz_compat.h +++ b/SSZipArchive/minizip/mz_compat.h @@ -128,7 +128,7 @@ ZEXPORT void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def); // SSZipArchive 2.x+ uses dos_date #define MZ_COMPAT_VERSION 120 -#if MZ_COMPAT_VERSION <= 110 +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION <= 110 #define mz_dos_date dosDate #else #define mz_dos_date dos_date @@ -138,10 +138,10 @@ typedef struct tm tm_unz; typedef struct tm tm_zip; typedef struct { - uint32_t mz_dos_date; - struct tm tmz_date; - uint16_t internal_fa; /* internal file attributes 2 bytes */ - uint32_t external_fa; /* external file attributes 4 bytes */ + struct tm tmz_date; /* date in understandable format */ + unsigned long mz_dos_date; /* if dos_date == 0, tmz_date is used */ + unsigned long internal_fa; /* internal file attributes 2 bytes */ + unsigned long external_fa; /* external file attributes 4 bytes */ } zip_fileinfo; typedef const char *zipcharpc; @@ -182,6 +182,10 @@ ZEXPORT void* zipGetStream_MZ(zipFile file); ZEXPORT int zipOpenNewFileInZip(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, int compression_method, int level); +ZEXPORT int zipOpenNewFileInZip64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global, + uint16_t size_extrafield_global, const char *comment, int compression_method, int level, + int zip64); ZEXPORT int zipOpenNewFileInZip_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, int compression_method, int level, @@ -222,8 +226,8 @@ ZEXPORT int zipOpenNewFileInZip5(zipFile file, const char *filename, const z ZEXPORT int zipWriteInFileInZip(zipFile file, const void *buf, uint32_t len); -ZEXPORT int zipCloseFileInZipRaw(zipFile file, unsigned long uncompressed_size, uint32_t crc32); -ZEXPORT int zipCloseFileInZipRaw64(zipFile file, uint64_t uncompressed_size, uint32_t crc32); +ZEXPORT int zipCloseFileInZipRaw(zipFile file, unsigned long uncompressed_size, unsigned long crc32); +ZEXPORT int zipCloseFileInZipRaw64(zipFile file, uint64_t uncompressed_size, unsigned long crc32); ZEXPORT int zipCloseFileInZip(zipFile file); ZEXPORT int zipCloseFileInZip64(zipFile file); @@ -258,7 +262,48 @@ typedef void *unzFile; /***************************************************************************/ -typedef int (*unzFileNameComparer)(unzFile file, const char *filename1, const char *filename2); +typedef struct unz_global_info64_s { + uint64_t number_entry; /* total number of entries in the central dir on this disk */ + unsigned long size_comment; /* size of the global comment of the zipfile */ + uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */ +} unz_global_info64; + +typedef struct unz_file_info64_s { + unsigned long version; /* version made by 2 bytes */ + unsigned long version_needed; /* version needed to extract 2 bytes */ + unsigned long flag; /* general purpose bit flag 2 bytes */ + unsigned long compression_method; /* compression method 2 bytes */ + unsigned long mz_dos_date; /* last mod file date in Dos fmt 4 bytes */ + unsigned long crc; /* crc-32 4 bytes */ + uint64_t compressed_size; /* compressed size 8 bytes */ + uint64_t uncompressed_size; /* uncompressed size 8 bytes */ + unsigned long size_filename; /* filename length 2 bytes */ + unsigned long size_file_extra; /* extra field length 2 bytes */ + unsigned long size_file_comment; /* file comment length 2 bytes */ + + unsigned long disk_num_start; /* disk number start 4 bytes */ + unsigned long internal_fa; /* internal file attributes 2 bytes */ + unsigned long external_fa; /* external file attributes 4 bytes */ + + struct tm tmu_date; + + uint64_t disk_offset; + + uint16_t size_file_extra_internal; +} unz_file_info64; + +/***************************************************************************/ + +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION < 110 +/* Possible values: + 0 - Uses OS default, e.g. Windows ignores case. + 1 - Is case sensitive. + >= 2 - Ignore case. +*/ +typedef int unzFileNameCase; +#else +typedef int (*unzFileNameComparer)(unzFile file, const char* filename1, const char* filename2); +#endif typedef int (*unzIteratorFunction)(unzFile file); typedef int (*unzIteratorFunction2)(unzFile file, unz_file_info64 *pfile_info, char *filename, uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, @@ -299,7 +344,11 @@ ZEXPORT int unzGetCurrentFileInfo64(unzFile file, unz_file_info64 * pfile_in ZEXPORT int unzGoToFirstFile(unzFile file); ZEXPORT int unzGoToNextFile(unzFile file); -ZEXPORT int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func); +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION < 110 +ZEXPORT int unzLocateFile(unzFile file, const char *filename, unzFileNameCase filename_case); +#else +ZEXPORT int unzLocateFile(unzFile file, const char* filename, unzFileNameComparer filename_compare_func); +#endif ZEXPORT int unzGetLocalExtrafield(unzFile file, void *buf, unsigned int len); diff --git a/SSZipArchive/minizip/mz_crypt.c b/SSZipArchive/minizip/mz_crypt.c index 0f3f284..4c8d659 100644 --- a/SSZipArchive/minizip/mz_crypt.c +++ b/SSZipArchive/minizip/mz_crypt.c @@ -121,9 +121,14 @@ int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *sa memset(key, 0, key_length); - mz_crypt_hmac_create(&hmac1); - mz_crypt_hmac_create(&hmac2); - mz_crypt_hmac_create(&hmac3); + hmac1 = mz_crypt_hmac_create(); + hmac2 = mz_crypt_hmac_create(); + hmac3 = mz_crypt_hmac_create(); + + if (!hmac1 || !hmac2 || !hmac3) { + err = MZ_MEM_ERROR; + goto pbkdf2_cleanup; + } mz_crypt_hmac_set_algorithm(hmac1, MZ_HASH_SHA1); mz_crypt_hmac_set_algorithm(hmac2, MZ_HASH_SHA1); @@ -174,6 +179,7 @@ int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *sa key[k++] = ux[j++]; } +pbkdf2_cleanup: /* hmac3 uses the same provider as hmac2, so it must be deleted before the context is destroyed. */ mz_crypt_hmac_delete(&hmac3); diff --git a/SSZipArchive/minizip/mz_crypt.h b/SSZipArchive/minizip/mz_crypt.h index 9a341fc..1837af8 100644 --- a/SSZipArchive/minizip/mz_crypt.h +++ b/SSZipArchive/minizip/mz_crypt.h @@ -30,17 +30,21 @@ void mz_crypt_sha_reset(void *handle); int32_t mz_crypt_sha_begin(void *handle); int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size); int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size); -void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm); -void* mz_crypt_sha_create(void **handle); +int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm); +void* mz_crypt_sha_create(void); void mz_crypt_sha_delete(void **handle); void mz_crypt_aes_reset(void *handle); -int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size); -int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size); -int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length); -int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length); +int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size); +int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size); +int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size); +int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_size); +int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, + const void *iv, int32_t iv_length); +int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, + const void *iv, int32_t iv_length); void mz_crypt_aes_set_mode(void *handle, int32_t mode); -void* mz_crypt_aes_create(void **handle); +void* mz_crypt_aes_create(void); void mz_crypt_aes_delete(void **handle); void mz_crypt_hmac_reset(void *handle); @@ -49,13 +53,9 @@ int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size); int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size); int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle); void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm); -void* mz_crypt_hmac_create(void **handle); +void* mz_crypt_hmac_create(void); void mz_crypt_hmac_delete(void **handle); -int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size, - const char *cert_pwd, uint8_t **signature, int32_t *signature_size); -int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size); - /***************************************************************************/ #ifdef __cplusplus diff --git a/SSZipArchive/minizip/mz_crypt_apple.c b/SSZipArchive/minizip/mz_crypt_apple.c index 6acab3e..8485c6a 100644 --- a/SSZipArchive/minizip/mz_crypt_apple.c +++ b/SSZipArchive/minizip/mz_crypt_apple.c @@ -9,6 +9,7 @@ */ #include "mz.h" +#include "mz_crypt.h" #include #include @@ -19,6 +20,26 @@ /***************************************************************************/ +#ifndef MZ_TARGET_APPSTORE +#define MZ_TARGET_APPSTORE 1 +#endif + +/* Avoid use of private API for App Store as Apple does not allow it. Zip format doesn't need GCM. */ +#if !MZ_TARGET_APPSTORE +enum { + kCCModeGCM = 11, +}; + +CCCryptorStatus CCCryptorGCMReset(CCCryptorRef cryptorRef); +CCCryptorStatus CCCryptorGCMAddIV(CCCryptorRef cryptorRef, const void *iv, size_t ivLen); +CCCryptorStatus CCCryptorGCMAddAAD(CCCryptorRef cryptorRef, const void *aData, size_t aDataLen); +CCCryptorStatus CCCryptorGCMEncrypt(CCCryptorRef cryptorRef, const void *dataIn, size_t dataInLength, void *dataOut); +CCCryptorStatus CCCryptorGCMDecrypt(CCCryptorRef cryptorRef, const void *dataIn, size_t dataInLength, void *dataOut); +CCCryptorStatus CCCryptorGCMFinal(CCCryptorRef cryptorRef, void *tagOut, size_t *tagLength); +#endif + +/***************************************************************************/ + int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { if (SecRandomCopyBytes(kSecRandomDefault, size, buf) != errSecSuccess) return 0; @@ -151,23 +172,20 @@ int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) { return MZ_OK; } -void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) { +int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) { mz_crypt_sha *sha = (mz_crypt_sha *)handle; - if (MZ_HASH_SHA1 <= algorithm && algorithm <= MZ_HASH_SHA512) - sha->algorithm = algorithm; + if (algorithm < MZ_HASH_SHA1 || algorithm > MZ_HASH_SHA512) + return MZ_PARAM_ERROR; + sha->algorithm = algorithm; + return MZ_OK; } -void *mz_crypt_sha_create(void **handle) { - mz_crypt_sha *sha = NULL; - - sha = (mz_crypt_sha *)calloc(1, sizeof(mz_crypt_sha)); +void *mz_crypt_sha_create(void) { + mz_crypt_sha *sha = (mz_crypt_sha *)calloc(1, sizeof(mz_crypt_sha)); if (sha) { memset(sha, 0, sizeof(mz_crypt_sha)); sha->algorithm = MZ_HASH_SHA256; } - if (handle) - *handle = sha; - return sha; } @@ -193,7 +211,7 @@ typedef struct mz_crypt_aes_s { /***************************************************************************/ -void mz_crypt_aes_reset(void *handle) { +static void mz_crypt_aes_free(void *handle) { mz_crypt_aes *aes = (mz_crypt_aes *)handle; if (aes->crypt) @@ -201,72 +219,180 @@ void mz_crypt_aes_reset(void *handle) { aes->crypt = NULL; } -int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size) { +void mz_crypt_aes_reset(void *handle) { + mz_crypt_aes_free(handle); +} + +int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { mz_crypt_aes *aes = (mz_crypt_aes *)handle; size_t data_moved = 0; - if (!aes || !buf) - return MZ_PARAM_ERROR; - if (size != MZ_AES_BLOCK_SIZE) + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || !aes->crypt) return MZ_PARAM_ERROR; - aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved); + if (aes->mode == MZ_AES_MODE_GCM) { +#if MZ_TARGET_APPSTORE + return MZ_SUPPORT_ERROR; +#else + if (aad && aad_size > 0) { + aes->error = CCCryptorGCMAddAAD(aes->crypt, aad, aad_size); + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + } + aes->error = CCCryptorGCMEncrypt(aes->crypt, buf, size, buf); +#endif + } else { + if (aad && aad_size > 0) + return MZ_PARAM_ERROR; + aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved); + } if (aes->error != kCCSuccess) - return MZ_HASH_ERROR; + return MZ_CRYPT_ERROR; return size; } -int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size) { +int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; +#if !MZ_TARGET_APPSTORE + size_t tag_outsize = tag_size; +#endif + + if (!aes || !tag || !tag_size || !aes->crypt || aes->mode != MZ_AES_MODE_GCM) + return MZ_PARAM_ERROR; + +#if MZ_TARGET_APPSTORE + return MZ_SUPPORT_ERROR; +#else + aes->error = CCCryptorGCMEncrypt(aes->crypt, buf, size, buf); + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + + aes->error = CCCryptorGCMFinal(aes->crypt, tag, &tag_outsize); + + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + + return size; +#endif +} + +int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { mz_crypt_aes *aes = (mz_crypt_aes *)handle; size_t data_moved = 0; - if (!aes || !buf) - return MZ_PARAM_ERROR; - if (size != MZ_AES_BLOCK_SIZE) + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || !aes->crypt) return MZ_PARAM_ERROR; - aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved); + if (aes->mode == MZ_AES_MODE_GCM) { +#if MZ_TARGET_APPSTORE + return MZ_SUPPORT_ERROR; +#else + if (aad && aad_size > 0) { + aes->error = CCCryptorGCMAddAAD(aes->crypt, aad, aad_size); + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + } + aes->error = CCCryptorGCMDecrypt(aes->crypt, buf, size, buf); +#endif + } else { + if (aad && aad_size > 0) + return MZ_PARAM_ERROR; + aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved); + } if (aes->error != kCCSuccess) - return MZ_HASH_ERROR; + return MZ_CRYPT_ERROR; return size; } -int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length) { +int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_length) { mz_crypt_aes *aes = (mz_crypt_aes *)handle; +#if !MZ_TARGET_APPSTORE + uint8_t tag_actual_buf[MZ_AES_BLOCK_SIZE]; + size_t tag_actual_len = sizeof(tag_actual_buf); + uint8_t *tag_actual = tag_actual_buf; + int32_t c = tag_length; + int32_t is_ok = 0; +#endif - if (!aes || !key || !key_length) + if (!aes || !tag || !tag_length || !aes->crypt || aes->mode != MZ_AES_MODE_GCM) + return MZ_PARAM_ERROR; + +#if MZ_TARGET_APPSTORE + return MZ_SUPPORT_ERROR; +#else + aes->error = CCCryptorGCMDecrypt(aes->crypt, buf, size, buf); + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + + /* CCCryptorGCMFinal does not verify tag */ + aes->error = CCCryptorGCMFinal(aes->crypt, tag_actual, &tag_actual_len); + + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + if (tag_length != (int32_t)tag_actual_len) + return MZ_CRYPT_ERROR; + + /* Timing safe comparison */ + for (; c > 0; c--) + is_ok |= *tag++ ^ *tag_actual++; + + if (is_ok) + return MZ_CRYPT_ERROR; + + return size; +#endif +} + +static int32_t mz_crypt_aes_set_key(void *handle, const void *key, int32_t key_length, + const void *iv, int32_t iv_length, CCOperation op) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + CCMode mode; + + if (aes->mode == MZ_AES_MODE_CBC) + mode = kCCModeCBC; + else if (aes->mode == MZ_AES_MODE_ECB) + mode = kCCModeECB; + else if (aes->mode == MZ_AES_MODE_GCM) +#if !MZ_TARGET_APPSTORE + mode = kCCModeGCM; +#else + return MZ_SUPPORT_ERROR; +#endif + else return MZ_PARAM_ERROR; mz_crypt_aes_reset(handle); - aes->error = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode, - key, key_length, NULL, &aes->crypt); + aes->error = CCCryptorCreateWithMode(op, mode, kCCAlgorithmAES, ccNoPadding, iv, key, key_length, + NULL, 0, 0, 0, &aes->crypt); if (aes->error != kCCSuccess) return MZ_HASH_ERROR; +#if !MZ_TARGET_APPSTORE + if (aes->mode == MZ_AES_MODE_GCM) { + aes->error = CCCryptorGCMAddIV(aes->crypt, iv, iv_length); + + if (aes->error != kCCSuccess) + return MZ_HASH_ERROR; + } +#endif + return MZ_OK; } -int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length) { - mz_crypt_aes *aes = (mz_crypt_aes *)handle; +int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, + const void *iv, int32_t iv_length) { + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length, kCCEncrypt); +} - if (!aes || !key || !key_length) - return MZ_PARAM_ERROR; - - mz_crypt_aes_reset(handle); - - aes->error = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES, kCCOptionECBMode, - key, key_length, NULL, &aes->crypt); - - if (aes->error != kCCSuccess) - return MZ_HASH_ERROR; - - return MZ_OK; +int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, + const void *iv, int32_t iv_length) { + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length, kCCDecrypt); } void mz_crypt_aes_set_mode(void *handle, int32_t mode) { @@ -274,13 +400,8 @@ void mz_crypt_aes_set_mode(void *handle, int32_t mode) { aes->mode = mode; } -void *mz_crypt_aes_create(void **handle) { - mz_crypt_aes *aes = NULL; - - aes = (mz_crypt_aes *)calloc(1, sizeof(mz_crypt_aes)); - if (handle) - *handle = aes; - +void *mz_crypt_aes_create(void) { + mz_crypt_aes *aes = (mz_crypt_aes *)calloc(1, sizeof(mz_crypt_aes)); return aes; } @@ -290,7 +411,7 @@ void mz_crypt_aes_delete(void **handle) { return; aes = (mz_crypt_aes *)*handle; if (aes) { - mz_crypt_aes_reset(*handle); + mz_crypt_aes_free(*handle); free(aes); } *handle = NULL; @@ -383,15 +504,10 @@ int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) { return MZ_OK; } -void *mz_crypt_hmac_create(void **handle) { - mz_crypt_hmac *hmac = NULL; - - hmac = (mz_crypt_hmac *)calloc(1, sizeof(mz_crypt_hmac)); +void *mz_crypt_hmac_create(void) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)calloc(1, sizeof(mz_crypt_hmac)); if (hmac) hmac->algorithm = MZ_HASH_SHA256; - if (handle) - *handle = hmac; - return hmac; } @@ -406,121 +522,3 @@ void mz_crypt_hmac_delete(void **handle) { } *handle = NULL; } - -/***************************************************************************/ - -#if defined(MZ_ZIP_SIGNING) -int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size, - const char *cert_pwd, uint8_t **signature, int32_t *signature_size) { - CFStringRef password_ref = NULL; - CFDictionaryRef options_dict = NULL; - CFDictionaryRef identity_trust = NULL; - CFDataRef signature_out = NULL; - CFDataRef pkcs12_data = NULL; - CFArrayRef items = 0; - SecIdentityRef identity = NULL; - SecTrustRef trust = NULL; - OSStatus status = noErr; - const void *options_key[2] = {kSecImportExportPassphrase, kSecReturnRef}; - const void *options_values[2] = {0, kCFBooleanTrue}; - int32_t err = MZ_SIGN_ERROR; - - if (!message || !cert_data || !signature || !signature_size) - return MZ_PARAM_ERROR; - - *signature = NULL; - *signature_size = 0; - - password_ref = CFStringCreateWithCString(0, cert_pwd, kCFStringEncodingUTF8); - options_values[0] = password_ref; - - options_dict = CFDictionaryCreate(0, options_key, options_values, 2, 0, 0); - if (options_dict) - pkcs12_data = CFDataCreate(0, cert_data, cert_data_size); - if (pkcs12_data) - status = SecPKCS12Import(pkcs12_data, options_dict, &items); - if (status == noErr) - identity_trust = CFArrayGetValueAtIndex(items, 0); - if (identity_trust) - identity = (SecIdentityRef)CFDictionaryGetValue(identity_trust, kSecImportItemIdentity); - if (identity) - trust = (SecTrustRef)CFDictionaryGetValue(identity_trust, kSecImportItemTrust); - if (trust) { - status = CMSEncodeContent(identity, NULL, NULL, FALSE, 0, message, message_size, &signature_out); - - if (status == errSecSuccess) { - *signature_size = CFDataGetLength(signature_out); - *signature = (uint8_t *)malloc(*signature_size); - - memcpy(*signature, CFDataGetBytePtr(signature_out), *signature_size); - - err = MZ_OK; - } - } - - if (signature_out) - CFRelease(signature_out); - if (items) - CFRelease(items); - if (pkcs12_data) - CFRelease(pkcs12_data); - if (options_dict) - CFRelease(options_dict); - if (password_ref) - CFRelease(password_ref); - - return err; -} - -int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size) { - CMSDecoderRef decoder = NULL; - CMSSignerStatus signer_status = 0; - CFDataRef message_out = NULL; - SecPolicyRef trust_policy = NULL; - OSStatus status = noErr; - OSStatus verify_status = noErr; - size_t signer_count = 0; - size_t i = 0; - int32_t err = MZ_SIGN_ERROR; - - if (!message || !signature) - return MZ_PARAM_ERROR; - - status = CMSDecoderCreate(&decoder); - if (status == errSecSuccess) - status = CMSDecoderUpdateMessage(decoder, signature, signature_size); - if (status == errSecSuccess) - status = CMSDecoderFinalizeMessage(decoder); - if (status == errSecSuccess) - trust_policy = SecPolicyCreateBasicX509(); - - if (status == errSecSuccess && trust_policy) { - CMSDecoderGetNumSigners(decoder, &signer_count); - if (signer_count > 0) - err = MZ_OK; - for (i = 0; i < signer_count; i += 1) { - status = CMSDecoderCopySignerStatus(decoder, i, trust_policy, TRUE, &signer_status, NULL, &verify_status); - if (status != errSecSuccess || verify_status != 0 || signer_status != kCMSSignerValid) { - err = MZ_SIGN_ERROR; - break; - } - } - } - - if (err == MZ_OK) { - status = CMSDecoderCopyContent(decoder, &message_out); - if ((status != errSecSuccess) || - (CFDataGetLength(message_out) != message_size) || - (memcmp(message, CFDataGetBytePtr(message_out), message_size) != 0)) - err = MZ_SIGN_ERROR; - } - - if (trust_policy) - CFRelease(trust_policy); - if (decoder) - CFRelease(decoder); - - return err; -} - -#endif diff --git a/SSZipArchive/minizip/mz_os.c b/SSZipArchive/minizip/mz_os.c index 6a37060..57b1722 100644 --- a/SSZipArchive/minizip/mz_os.c +++ b/SSZipArchive/minizip/mz_os.c @@ -68,7 +68,7 @@ int32_t mz_path_remove_slash(char *path) { int32_t mz_path_has_slash(const char *path) { int32_t path_len = (int32_t)strlen(path); - if (path[path_len - 1] != '\\' && path[path_len - 1] != '/') + if (path_len > 0 && path[path_len - 1] != '\\' && path[path_len - 1] != '/') return MZ_EXIST_ERROR; return MZ_OK; } @@ -171,11 +171,11 @@ int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) { if ((*check == 0) || (*check == '\\' || *check == '/')) { source += (check - source); - /* Search backwards for previous slash */ + /* Search backwards for previous slash or the start of the output string */ if (target != output) { target -= 1; do { - if ((*target == '\\') || (*target == '/')) + if ((target == output) ||(*target == '\\') || (*target == '/')) break; target -= 1; @@ -283,6 +283,9 @@ int32_t mz_dir_make(const char *path) { char *match = NULL; char hold = 0; + if (!*path) + return MZ_OK; + current_dir = strdup(path); if (!current_dir) return MZ_MEM_ERROR; @@ -320,10 +323,11 @@ int32_t mz_file_get_crc(const char *path, uint32_t *result_crc) { int32_t err = MZ_OK; uint8_t buf[16384]; - mz_stream_os_create(&stream); + stream = mz_stream_os_create(); + if (!stream) + return MZ_MEM_ERROR; err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ); - if (err == MZ_OK) { do { read = mz_stream_os_read(stream, buf, sizeof(buf)); diff --git a/SSZipArchive/minizip/mz_os.h b/SSZipArchive/minizip/mz_os.h index 4505bc3..ad6ea4f 100644 --- a/SSZipArchive/minizip/mz_os.h +++ b/SSZipArchive/minizip/mz_os.h @@ -107,10 +107,10 @@ wchar_t *mz_os_unicode_string_create(const char *string, int32_t encoding); void mz_os_unicode_string_delete(wchar_t **string); /* Delete a unicode string that was created */ -uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding); +char *mz_os_utf8_string_create(const char *string, int32_t encoding); /* Create a utf8 string from a string with another encoding */ -void mz_os_utf8_string_delete(uint8_t **string); +void mz_os_utf8_string_delete(char **string); /* Delete a utf8 string that was created */ int32_t mz_os_rand(uint8_t *buf, int32_t size); diff --git a/SSZipArchive/minizip/mz_os_posix.c b/SSZipArchive/minizip/mz_os_posix.c index d7d329b..6736d09 100644 --- a/SSZipArchive/minizip/mz_os_posix.c +++ b/SSZipArchive/minizip/mz_os_posix.c @@ -40,14 +40,14 @@ /***************************************************************************/ #if defined(HAVE_ICONV) -uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) { +char *mz_os_utf8_string_create(const char *string, int32_t encoding) { iconv_t cd; const char *from_encoding = NULL; size_t result = 0; size_t string_length = 0; size_t string_utf8_size = 0; - uint8_t *string_utf8 = NULL; - uint8_t *string_utf8_ptr = NULL; + char *string_utf8 = NULL; + char *string_utf8_ptr = NULL; if (!string) return NULL; @@ -71,7 +71,7 @@ uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) { string_length = strlen(string); string_utf8_size = string_length * 2; - string_utf8 = (uint8_t *)calloc((int32_t)(string_utf8_size + 1), sizeof(char)); + string_utf8 = (char *)calloc((int32_t)(string_utf8_size + 1), sizeof(char)); string_utf8_ptr = string_utf8; if (string_utf8) { @@ -89,12 +89,12 @@ uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) { return string_utf8; } #else -uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) { - return (uint8_t *)strdup(string); +char *mz_os_utf8_string_create(const char *string, int32_t encoding) { + return strdup(string); } #endif -void mz_os_utf8_string_delete(uint8_t **string) { +void mz_os_utf8_string_delete(char **string) { if (string) { free(*string); *string = NULL; diff --git a/SSZipArchive/minizip/mz_strm.c b/SSZipArchive/minizip/mz_strm.c index 35d4c62..edcbafa 100644 --- a/SSZipArchive/minizip/mz_strm.c +++ b/SSZipArchive/minizip/mz_strm.c @@ -397,10 +397,10 @@ int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value) { return strm->vtbl->set_prop_int64(stream, prop, value); } -void *mz_stream_create(void **stream, mz_stream_vtbl *vtbl) { - if (!stream || !vtbl || !vtbl->create) +void *mz_stream_create(mz_stream_vtbl *vtbl) { + if (!vtbl || !vtbl->create) return NULL; - return vtbl->create(stream); + return vtbl->create(); } void mz_stream_delete(void **stream) { @@ -533,15 +533,10 @@ static mz_stream_vtbl mz_stream_raw_vtbl = { /***************************************************************************/ -void *mz_stream_raw_create(void **stream) { - mz_stream_raw *raw = NULL; - - raw = (mz_stream_raw *)calloc(1, sizeof(mz_stream_raw)); +void *mz_stream_raw_create(void) { + mz_stream_raw *raw = (mz_stream_raw *)calloc(1, sizeof(mz_stream_raw)); if (raw) raw->stream.vtbl = &mz_stream_raw_vtbl; - if (stream) - *stream = raw; - return raw; } diff --git a/SSZipArchive/minizip/mz_strm.h b/SSZipArchive/minizip/mz_strm.h index 5f88015..f65baab 100644 --- a/SSZipArchive/minizip/mz_strm.h +++ b/SSZipArchive/minizip/mz_strm.h @@ -39,7 +39,7 @@ typedef int64_t (*mz_stream_tell_cb) (void *stream); typedef int32_t (*mz_stream_seek_cb) (void *stream, int64_t offset, int32_t origin); typedef int32_t (*mz_stream_close_cb) (void *stream); typedef int32_t (*mz_stream_error_cb) (void *stream); -typedef void* (*mz_stream_create_cb) (void **stream); +typedef void* (*mz_stream_create_cb) (void); typedef void (*mz_stream_destroy_cb) (void **stream); typedef int32_t (*mz_stream_get_prop_int64_cb) (void *stream, int32_t prop, int64_t *value); @@ -103,7 +103,7 @@ void* mz_stream_get_interface(void *stream); int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value); int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value); -void* mz_stream_create(void **stream, mz_stream_vtbl *vtbl); +void* mz_stream_create(mz_stream_vtbl *vtbl); void mz_stream_delete(void **stream); /***************************************************************************/ @@ -120,7 +120,7 @@ int32_t mz_stream_raw_error(void *stream); int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value); int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value); -void* mz_stream_raw_create(void **stream); +void* mz_stream_raw_create(void); void mz_stream_raw_delete(void **stream); /***************************************************************************/ diff --git a/SSZipArchive/minizip/mz_strm_buf.c b/SSZipArchive/minizip/mz_strm_buf.c index 3081d53..441b6f7 100644 --- a/SSZipArchive/minizip/mz_strm_buf.c +++ b/SSZipArchive/minizip/mz_strm_buf.c @@ -356,15 +356,10 @@ int32_t mz_stream_buffered_error(void *stream) { return mz_stream_error(buffered->stream.base); } -void *mz_stream_buffered_create(void **stream) { - mz_stream_buffered *buffered = NULL; - - buffered = (mz_stream_buffered *)calloc(1, sizeof(mz_stream_buffered)); +void *mz_stream_buffered_create(void) { + mz_stream_buffered *buffered = (mz_stream_buffered *)calloc(1, sizeof(mz_stream_buffered)); if (buffered) buffered->stream.vtbl = &mz_stream_buffered_vtbl; - if (stream) - *stream = buffered; - return buffered; } diff --git a/SSZipArchive/minizip/mz_strm_buf.h b/SSZipArchive/minizip/mz_strm_buf.h index 93eea26..9850090 100644 --- a/SSZipArchive/minizip/mz_strm_buf.h +++ b/SSZipArchive/minizip/mz_strm_buf.h @@ -28,7 +28,7 @@ int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin); int32_t mz_stream_buffered_close(void *stream); int32_t mz_stream_buffered_error(void *stream); -void* mz_stream_buffered_create(void **stream); +void* mz_stream_buffered_create(void); void mz_stream_buffered_delete(void **stream); void* mz_stream_buffered_get_interface(void); diff --git a/SSZipArchive/minizip/mz_strm_mem.c b/SSZipArchive/minizip/mz_strm_mem.c index 9a78dc1..45881b2 100644 --- a/SSZipArchive/minizip/mz_strm_mem.c +++ b/SSZipArchive/minizip/mz_strm_mem.c @@ -237,17 +237,12 @@ void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size) { mem->grow_size = grow_size; } -void *mz_stream_mem_create(void **stream) { - mz_stream_mem *mem = NULL; - - mem = (mz_stream_mem *)calloc(1, sizeof(mz_stream_mem)); +void *mz_stream_mem_create(void) { + mz_stream_mem *mem = (mz_stream_mem *)calloc(1, sizeof(mz_stream_mem)); if (mem) { mem->stream.vtbl = &mz_stream_mem_vtbl; mem->grow_size = 4096; } - if (stream) - *stream = mem; - return mem; } diff --git a/SSZipArchive/minizip/mz_strm_mem.h b/SSZipArchive/minizip/mz_strm_mem.h index 22a12de..ed6f957 100644 --- a/SSZipArchive/minizip/mz_strm_mem.h +++ b/SSZipArchive/minizip/mz_strm_mem.h @@ -34,7 +34,7 @@ void mz_stream_mem_get_buffer_length(void *stream, int32_t *length); void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit); void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size); -void* mz_stream_mem_create(void **stream); +void* mz_stream_mem_create(void); void mz_stream_mem_delete(void **stream); void* mz_stream_mem_get_interface(void); diff --git a/SSZipArchive/minizip/mz_strm_os.h b/SSZipArchive/minizip/mz_strm_os.h index 83d292b..0ed279f 100644 --- a/SSZipArchive/minizip/mz_strm_os.h +++ b/SSZipArchive/minizip/mz_strm_os.h @@ -26,7 +26,7 @@ int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin); int32_t mz_stream_os_close(void *stream); int32_t mz_stream_os_error(void *stream); -void* mz_stream_os_create(void **stream); +void* mz_stream_os_create(void); void mz_stream_os_delete(void **stream); void* mz_stream_os_get_interface(void); diff --git a/SSZipArchive/minizip/mz_strm_os_posix.c b/SSZipArchive/minizip/mz_strm_os_posix.c index 60ff502..b351ebb 100644 --- a/SSZipArchive/minizip/mz_strm_os_posix.c +++ b/SSZipArchive/minizip/mz_strm_os_posix.c @@ -176,15 +176,10 @@ int32_t mz_stream_os_error(void *stream) { return posix->error; } -void *mz_stream_os_create(void **stream) { - mz_stream_posix *posix = NULL; - - posix = (mz_stream_posix *)calloc(1, sizeof(mz_stream_posix)); +void *mz_stream_os_create(void) { + mz_stream_posix *posix = (mz_stream_posix *)calloc(1, sizeof(mz_stream_posix)); if (posix) posix->stream.vtbl = &mz_stream_os_vtbl; - if (stream) - *stream = posix; - return posix; } diff --git a/SSZipArchive/minizip/mz_strm_pkcrypt.c b/SSZipArchive/minizip/mz_strm_pkcrypt.c index 1791b15..4116329 100644 --- a/SSZipArchive/minizip/mz_strm_pkcrypt.c +++ b/SSZipArchive/minizip/mz_strm_pkcrypt.c @@ -56,6 +56,7 @@ typedef struct mz_stream_pkcrypt_s { uint32_t keys[3]; /* keys defining the pseudo-random sequence */ uint8_t verify1; uint8_t verify2; + uint16_t verify_version; const char *password; } mz_stream_pkcrypt; @@ -161,10 +162,14 @@ int32_t mz_stream_pkcrypt_open(void *stream, const char *path, int32_t mode) { verify1 = mz_stream_pkcrypt_decode(stream, header[i++]); verify2 = mz_stream_pkcrypt_decode(stream, header[i++]); - /* Older versions used 2 byte check, newer versions use 1 byte check. */ - MZ_UNUSED(verify1); - if ((verify2 != 0) && (verify2 != pkcrypt->verify2)) + /* PKZIP 2.0 and higher use 1 byte check, older versions used 2 byte check. + See app note section 6.1.6. */ + if (verify2 != pkcrypt->verify2) return MZ_PASSWORD_ERROR; + if (pkcrypt->verify_version < 2) { + if (verify1 != pkcrypt->verify1) + return MZ_PASSWORD_ERROR; + } pkcrypt->total_in += MZ_PKCRYPT_HEADER_SIZE; } @@ -259,16 +264,18 @@ void mz_stream_pkcrypt_set_password(void *stream, const char *password) { pkcrypt->password = password; } -void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2) { +void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2, uint16_t version) { mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; pkcrypt->verify1 = verify1; pkcrypt->verify2 = verify2; + pkcrypt->verify_version = version; } -void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2) { +void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2, uint16_t *version) { mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; *verify1 = pkcrypt->verify1; *verify2 = pkcrypt->verify2; + *version = pkcrypt->verify_version; } int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value) { @@ -307,15 +314,10 @@ int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t val return MZ_OK; } -void *mz_stream_pkcrypt_create(void **stream) { - mz_stream_pkcrypt *pkcrypt = NULL; - - pkcrypt = (mz_stream_pkcrypt *)calloc(1, sizeof(mz_stream_pkcrypt)); +void *mz_stream_pkcrypt_create(void) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)calloc(1, sizeof(mz_stream_pkcrypt)); if (pkcrypt) pkcrypt->stream.vtbl = &mz_stream_pkcrypt_vtbl; - if (stream) - *stream = pkcrypt; - return pkcrypt; } diff --git a/SSZipArchive/minizip/mz_strm_pkcrypt.h b/SSZipArchive/minizip/mz_strm_pkcrypt.h index 1d6fb46..d9bdbaa 100644 --- a/SSZipArchive/minizip/mz_strm_pkcrypt.h +++ b/SSZipArchive/minizip/mz_strm_pkcrypt.h @@ -27,12 +27,12 @@ int32_t mz_stream_pkcrypt_close(void *stream); int32_t mz_stream_pkcrypt_error(void *stream); void mz_stream_pkcrypt_set_password(void *stream, const char *password); -void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2); -void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2); +void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2, uint16_t version); +void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2, uint16_t *version); int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value); int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value); -void* mz_stream_pkcrypt_create(void **stream); +void* mz_stream_pkcrypt_create(void); void mz_stream_pkcrypt_delete(void **stream); void* mz_stream_pkcrypt_get_interface(void); diff --git a/SSZipArchive/minizip/mz_strm_split.c b/SSZipArchive/minizip/mz_strm_split.c index 7b34543..a50392c 100644 --- a/SSZipArchive/minizip/mz_strm_split.c +++ b/SSZipArchive/minizip/mz_strm_split.c @@ -104,8 +104,13 @@ static int32_t mz_stream_split_open_disk(void *stream, int32_t number_disk) { mz_stream_split_print("Split - Goto disk - %s (disk %" PRId32 ")\n", split->path_disk, number_disk); /* If disk part doesn't exist during reading then return MZ_EXIST_ERROR */ - if (disk_part == MZ_OPEN_MODE_READ) - err = mz_os_file_exists(split->path_disk); + if (disk_part == MZ_OPEN_MODE_READ) { + if (strcmp(split->path_disk, split->path_cd) == 0) { + err = MZ_EXIST_ERROR; + } else { + err = mz_os_file_exists(split->path_disk); + } + } if (err == MZ_OK) err = mz_stream_open(split->stream.base, split->path_disk, split->mode); @@ -241,7 +246,6 @@ int32_t mz_stream_split_read(void *stream, void *buf, int32_t size) { err = mz_stream_split_goto_disk(stream, split->current_disk + 1); if (err == MZ_EXIST_ERROR) { split->current_disk = -1; - break; } if (err != MZ_OK) return err; @@ -397,15 +401,10 @@ int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value return MZ_OK; } -void *mz_stream_split_create(void **stream) { - mz_stream_split *split = NULL; - - split = (mz_stream_split *)calloc(1, sizeof(mz_stream_split)); +void *mz_stream_split_create(void) { + mz_stream_split *split = (mz_stream_split *)calloc(1, sizeof(mz_stream_split)); if (split) split->stream.vtbl = &mz_stream_split_vtbl; - if (stream) - *stream = split; - return split; } diff --git a/SSZipArchive/minizip/mz_strm_split.h b/SSZipArchive/minizip/mz_strm_split.h index d03054b..a5b74ed 100644 --- a/SSZipArchive/minizip/mz_strm_split.h +++ b/SSZipArchive/minizip/mz_strm_split.h @@ -29,7 +29,7 @@ int32_t mz_stream_split_error(void *stream); int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value); int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value); -void* mz_stream_split_create(void **stream); +void* mz_stream_split_create(void); void mz_stream_split_delete(void **stream); void* mz_stream_split_get_interface(void); diff --git a/SSZipArchive/minizip/mz_strm_wzaes.c b/SSZipArchive/minizip/mz_strm_wzaes.c index f4a5281..f1299c8 100644 --- a/SSZipArchive/minizip/mz_strm_wzaes.c +++ b/SSZipArchive/minizip/mz_strm_wzaes.c @@ -16,12 +16,13 @@ /***************************************************************************/ -#define MZ_AES_KEYING_ITERATIONS (1000) -#define MZ_AES_SALT_LENGTH(MODE) (4 * (MODE & 3) + 4) -#define MZ_AES_SALT_LENGTH_MAX (16) -#define MZ_AES_PW_LENGTH_MAX (128) -#define MZ_AES_PW_VERIFY_SIZE (2) -#define MZ_AES_AUTHCODE_SIZE (10) +#define MZ_AES_KEY_LENGTH(STRENGTH) (8 * (STRENGTH & 3) + 8) +#define MZ_AES_KEYING_ITERATIONS (1000) +#define MZ_AES_SALT_LENGTH(STRENGTH) (4 * (STRENGTH & 3) + 4) +#define MZ_AES_SALT_LENGTH_MAX (16) +#define MZ_AES_PW_LENGTH_MAX (128) +#define MZ_AES_PW_VERIFY_SIZE (2) +#define MZ_AES_AUTHCODE_SIZE (10) /***************************************************************************/ @@ -51,7 +52,7 @@ typedef struct mz_stream_wzaes_s { int64_t total_in; int64_t max_total_in; int64_t total_out; - int16_t encryption_mode; + uint8_t strength; const char *password; void *aes; uint32_t crypt_pos; @@ -88,10 +89,11 @@ int32_t mz_stream_wzaes_open(void *stream, const char *path, int32_t mode) { if (password_length > MZ_AES_PW_LENGTH_MAX) return MZ_PARAM_ERROR; - if (wzaes->encryption_mode < 1 || wzaes->encryption_mode > 3) + if (wzaes->strength < 1 || wzaes->strength > 3) return MZ_PARAM_ERROR; - salt_length = MZ_AES_SALT_LENGTH(wzaes->encryption_mode); + key_length = MZ_AES_KEY_LENGTH(wzaes->strength); + salt_length = MZ_AES_SALT_LENGTH(wzaes->strength); if (mode & MZ_OPEN_MODE_WRITE) { mz_crypt_rand(salt_value, salt_length); @@ -100,8 +102,6 @@ int32_t mz_stream_wzaes_open(void *stream, const char *path, int32_t mode) { return MZ_READ_ERROR; } - key_length = MZ_AES_KEY_LENGTH(wzaes->encryption_mode); - /* Derive the encryption and authentication keys and the password verifier */ mz_crypt_pbkdf2((uint8_t *)password, password_length, salt_value, salt_length, MZ_AES_KEYING_ITERATIONS, kbuf, 2 * key_length + MZ_AES_PW_VERIFY_SIZE); @@ -114,8 +114,7 @@ int32_t mz_stream_wzaes_open(void *stream, const char *path, int32_t mode) { /* Initialize for encryption using key 1 */ mz_crypt_aes_reset(wzaes->aes); - mz_crypt_aes_set_mode(wzaes->aes, wzaes->encryption_mode); - mz_crypt_aes_set_encrypt_key(wzaes->aes, kbuf, key_length); + mz_crypt_aes_set_encrypt_key(wzaes->aes, kbuf, key_length, NULL, 0); /* Initialize for authentication using key 2 */ mz_crypt_hmac_reset(wzaes->hmac); @@ -175,7 +174,7 @@ static int32_t mz_stream_wzaes_ctr_encrypt(void *stream, uint8_t *buf, int32_t s /* Encrypt the nonce using ECB mode to form next xor buffer */ memcpy(wzaes->crypt_block, wzaes->nonce, MZ_AES_BLOCK_SIZE); - mz_crypt_aes_encrypt(wzaes->aes, wzaes->crypt_block, sizeof(wzaes->crypt_block)); + mz_crypt_aes_encrypt(wzaes->aes, NULL, 0, wzaes->crypt_block, sizeof(wzaes->crypt_block)); pos = 0; } @@ -286,9 +285,9 @@ void mz_stream_wzaes_set_password(void *stream, const char *password) { wzaes->password = password; } -void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode) { +void mz_stream_wzaes_set_strength(void *stream, uint8_t strength) { mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; - wzaes->encryption_mode = encryption_mode; + wzaes->strength = strength; } int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value) { @@ -304,7 +303,7 @@ int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *valu *value = wzaes->max_total_in; break; case MZ_STREAM_PROP_HEADER_SIZE: - *value = MZ_AES_SALT_LENGTH((int64_t)wzaes->encryption_mode) + MZ_AES_PW_VERIFY_SIZE; + *value = MZ_AES_SALT_LENGTH((int64_t)wzaes->strength) + MZ_AES_PW_VERIFY_SIZE; break; case MZ_STREAM_PROP_FOOTER_SIZE: *value = MZ_AES_AUTHCODE_SIZE; @@ -327,20 +326,24 @@ int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value return MZ_OK; } -void *mz_stream_wzaes_create(void **stream) { - mz_stream_wzaes *wzaes = NULL; - - wzaes = (mz_stream_wzaes *)calloc(1, sizeof(mz_stream_wzaes)); +void *mz_stream_wzaes_create(void) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)calloc(1, sizeof(mz_stream_wzaes)); if (wzaes) { wzaes->stream.vtbl = &mz_stream_wzaes_vtbl; - wzaes->encryption_mode = MZ_AES_ENCRYPTION_MODE_256; + wzaes->strength = MZ_AES_STRENGTH_256; - mz_crypt_hmac_create(&wzaes->hmac); - mz_crypt_aes_create(&wzaes->aes); + wzaes->hmac = mz_crypt_hmac_create(); + if (!wzaes->hmac) { + free(wzaes); + return NULL; + } + wzaes->aes = mz_crypt_aes_create(); + if (!wzaes->aes) { + mz_crypt_hmac_delete(&wzaes->hmac); + free(wzaes); + return NULL; + } } - if (stream) - *stream = wzaes; - return wzaes; } diff --git a/SSZipArchive/minizip/mz_strm_wzaes.h b/SSZipArchive/minizip/mz_strm_wzaes.h index 5163c80..788166e 100644 --- a/SSZipArchive/minizip/mz_strm_wzaes.h +++ b/SSZipArchive/minizip/mz_strm_wzaes.h @@ -27,12 +27,12 @@ int32_t mz_stream_wzaes_close(void *stream); int32_t mz_stream_wzaes_error(void *stream); void mz_stream_wzaes_set_password(void *stream, const char *password); -void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode); +void mz_stream_wzaes_set_strength(void *stream, uint8_t strength); int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value); int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value); -void* mz_stream_wzaes_create(void **stream); +void* mz_stream_wzaes_create(void); void mz_stream_wzaes_delete(void **stream); void* mz_stream_wzaes_get_interface(void); diff --git a/SSZipArchive/minizip/mz_strm_zlib.c b/SSZipArchive/minizip/mz_strm_zlib.c index b7ac4d1..cba63fb 100644 --- a/SSZipArchive/minizip/mz_strm_zlib.c +++ b/SSZipArchive/minizip/mz_strm_zlib.c @@ -191,6 +191,8 @@ int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size) { } } while (zlib->zstream.avail_out > 0); + MZ_UNUSED(total_in); + if (zlib->error != 0) { /* Zlib errors are compatible with MZ */ return zlib->error; @@ -345,7 +347,10 @@ int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value) mz_stream_zlib *zlib = (mz_stream_zlib *)stream; switch (prop) { case MZ_STREAM_PROP_COMPRESS_LEVEL: - zlib->level = (int16_t)value; + if (value == MZ_COMPRESS_LEVEL_DEFAULT) + zlib->level = Z_DEFAULT_COMPRESSION; + else + zlib->level = (int16_t)value; break; case MZ_STREAM_PROP_TOTAL_IN_MAX: zlib->max_total_in = value; @@ -359,18 +364,13 @@ int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value) return MZ_OK; } -void *mz_stream_zlib_create(void **stream) { - mz_stream_zlib *zlib = NULL; - - zlib = (mz_stream_zlib *)calloc(1, sizeof(mz_stream_zlib)); +void *mz_stream_zlib_create(void) { + mz_stream_zlib *zlib = zlib = (mz_stream_zlib *)calloc(1, sizeof(mz_stream_zlib)); if (zlib) { zlib->stream.vtbl = &mz_stream_zlib_vtbl; zlib->level = Z_DEFAULT_COMPRESSION; zlib->window_bits = -MAX_WBITS; } - if (stream) - *stream = zlib; - return zlib; } diff --git a/SSZipArchive/minizip/mz_strm_zlib.h b/SSZipArchive/minizip/mz_strm_zlib.h index 4bdcdf8..bba0991 100644 --- a/SSZipArchive/minizip/mz_strm_zlib.h +++ b/SSZipArchive/minizip/mz_strm_zlib.h @@ -29,7 +29,7 @@ int32_t mz_stream_zlib_error(void *stream); int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value); int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value); -void* mz_stream_zlib_create(void **stream); +void* mz_stream_zlib_create(void); void mz_stream_zlib_delete(void **stream); void* mz_stream_zlib_get_interface(void); diff --git a/SSZipArchive/minizip/mz_zip.c b/SSZipArchive/minizip/mz_zip.c index e80550f..ba0307b 100644 --- a/SSZipArchive/minizip/mz_zip.c +++ b/SSZipArchive/minizip/mz_zip.c @@ -431,7 +431,7 @@ static int32_t mz_zip_entry_read_header(void *stream, uint8_t local, mz_zip_file /* Get AES encryption strength and actual compression method */ if (err == MZ_OK) { err = mz_stream_read_uint8(file_extra_stream, &value8); - file_info->aes_encryption_mode = value8; + file_info->aes_strength = value8; } if (err == MZ_OK) { err = mz_stream_read_uint16(file_extra_stream, &value16); @@ -643,7 +643,9 @@ static int32_t mz_zip_entry_write_header(void *stream, uint8_t local, mz_zip_fil /* Calculate extra field size and check for duplicates */ if (file_info->extrafield_size > 0) { - mz_stream_mem_create(&file_extra_stream); + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; mz_stream_mem_set_buffer(file_extra_stream, (void *)file_info->extrafield, file_info->extrafield_size); @@ -709,6 +711,10 @@ static int32_t mz_zip_entry_write_header(void *stream, uint8_t local, mz_zip_fil version_needed = 20; if (zip64) version_needed = 45; +#ifdef HAVE_BZIP2 + if (file_info->compression_method == MZ_COMPRESS_METHOD_BZIP2) + version_needed = 46; +#endif #ifdef HAVE_WZAES if ((file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) && (file_info->aes_version)) version_needed = 51; @@ -790,7 +796,7 @@ static int32_t mz_zip_entry_write_header(void *stream, uint8_t local, mz_zip_fil int32_t left = filename_length; /* Ensure all slashes are written as forward slashes according to 4.4.17.1 */ - while ((err == MZ_OK) && (backslash = strrchr(next, '\\'))) { + while ((err == MZ_OK) && (backslash = strchr(next, '\\'))) { int32_t part_length = (int32_t)(backslash - next); if (mz_stream_write(stream, next, part_length) != part_length || @@ -876,7 +882,7 @@ static int32_t mz_zip_entry_write_header(void *stream, uint8_t local, mz_zip_fil if (err == MZ_OK) err = mz_stream_write_uint8(stream, 'E'); if (err == MZ_OK) - err = mz_stream_write_uint8(stream, file_info->aes_encryption_mode); + err = mz_stream_write_uint8(stream, file_info->aes_strength); if (err == MZ_OK) err = mz_stream_write_uint16(stream, file_info->compression_method); } @@ -1112,7 +1118,7 @@ static int32_t mz_zip_write_cd(void *handle) { zip->disk_number_with_cd += 1; mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, -1); if ((zip->disk_number_with_cd > 0) && (zip->open_mode & MZ_OPEN_MODE_APPEND)) { - // Overwrite existing central directory if using split disks + /* Overwrite existing central directory if using split disks */ mz_stream_seek(zip->stream, 0, MZ_SEEK_SET); } @@ -1127,7 +1133,7 @@ static int32_t mz_zip_write_cd(void *handle) { zip->disk_number_with_cd, zip->number_entry, zip->cd_offset, zip->cd_size); if (zip->cd_size == 0 && zip->number_entry > 0) { - // Zip does not contain central directory, open with recovery option + /* Zip does not contain central directory, open with recovery option */ return MZ_FORMAT_ERROR; } @@ -1264,10 +1270,13 @@ static int32_t mz_zip_recover_cd(void *handle) { } else disk_number_with_cd = 1; + local_file_info_stream = mz_stream_mem_create(); + if (!local_file_info_stream) + return MZ_MEM_ERROR; + if (mz_stream_is_open(cd_mem_stream) != MZ_OK) err = mz_stream_mem_open(cd_mem_stream, NULL, MZ_OPEN_MODE_CREATE); - mz_stream_mem_create(&local_file_info_stream); mz_stream_mem_open(local_file_info_stream, NULL, MZ_OPEN_MODE_CREATE); if (err == MZ_OK) { @@ -1397,15 +1406,10 @@ static int32_t mz_zip_recover_cd(void *handle) { return MZ_OK; } -void *mz_zip_create(void **handle) { - mz_zip *zip = NULL; - - zip = (mz_zip *)calloc(1, sizeof(mz_zip)); +void *mz_zip_create(void) { + mz_zip *zip = (mz_zip *)calloc(1, sizeof(mz_zip)); if (zip) zip->data_descriptor = 1; - if (handle) - *handle = zip; - return zip; } @@ -1430,8 +1434,9 @@ int32_t mz_zip_open(void *handle, void *stream, int32_t mode) { mz_zip_print("Zip - Open\n"); zip->stream = stream; - - mz_stream_mem_create(&zip->cd_mem_stream); + zip->cd_mem_stream = mz_stream_mem_create(); + if (!zip->cd_mem_stream) + return MZ_MEM_ERROR; if (mode & MZ_OPEN_MODE_WRITE) { mz_stream_mem_open(zip->cd_mem_stream, NULL, MZ_OPEN_MODE_CREATE); @@ -1483,10 +1488,18 @@ int32_t mz_zip_open(void *handle, void *stream, int32_t mode) { } /* Memory streams used to store variable length file info data */ - mz_stream_mem_create(&zip->file_info_stream); + zip->file_info_stream = mz_stream_mem_create(); + if (!zip->file_info_stream) + return MZ_MEM_ERROR; + mz_stream_mem_open(zip->file_info_stream, NULL, MZ_OPEN_MODE_CREATE); - mz_stream_mem_create(&zip->local_file_info_stream); + zip->local_file_info_stream = mz_stream_mem_create(); + if (!zip->local_file_info_stream) { + mz_stream_delete(&zip->file_info_stream); + return MZ_MEM_ERROR; + } + mz_stream_mem_open(zip->local_file_info_stream, NULL, MZ_OPEN_MODE_CREATE); zip->open_mode = mode; @@ -1724,9 +1737,11 @@ static int32_t mz_zip_entry_open_int(void *handle, uint8_t raw, int16_t compress if ((err == MZ_OK) && (use_crypt)) { #ifdef HAVE_WZAES if (zip->file_info.aes_version) { - mz_stream_wzaes_create(&zip->crypt_stream); + zip->crypt_stream = mz_stream_wzaes_create(); + if (!zip->crypt_stream) + return MZ_MEM_ERROR; mz_stream_wzaes_set_password(zip->crypt_stream, password); - mz_stream_wzaes_set_encryption_mode(zip->crypt_stream, zip->file_info.aes_encryption_mode); + mz_stream_wzaes_set_strength(zip->crypt_stream, zip->file_info.aes_strength); } else #endif { @@ -1734,16 +1749,20 @@ static int32_t mz_zip_entry_open_int(void *handle, uint8_t raw, int16_t compress uint8_t verify1 = (uint8_t)((zip->file_info.pk_verify >> 8) & 0xff); uint8_t verify2 = (uint8_t)((zip->file_info.pk_verify) & 0xff); - mz_stream_pkcrypt_create(&zip->crypt_stream); + zip->crypt_stream = mz_stream_pkcrypt_create(); + if (!zip->crypt_stream) + return MZ_MEM_ERROR; mz_stream_pkcrypt_set_password(zip->crypt_stream, password); - mz_stream_pkcrypt_set_verify(zip->crypt_stream, verify1, verify2); + mz_stream_pkcrypt_set_verify(zip->crypt_stream, verify1, verify2, zip->file_info.version_needed); #endif } } if (err == MZ_OK) { if (!zip->crypt_stream) - mz_stream_raw_create(&zip->crypt_stream); + zip->crypt_stream = mz_stream_raw_create(); + if (!zip->crypt_stream) + return MZ_MEM_ERROR; mz_stream_set_base(zip->crypt_stream, zip->stream); @@ -1752,39 +1771,44 @@ static int32_t mz_zip_entry_open_int(void *handle, uint8_t raw, int16_t compress if (err == MZ_OK) { if (zip->entry_raw || zip->file_info.compression_method == MZ_COMPRESS_METHOD_STORE) - mz_stream_raw_create(&zip->compress_stream); + zip->compress_stream = mz_stream_raw_create(); #ifdef HAVE_ZLIB else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_DEFLATE) - mz_stream_zlib_create(&zip->compress_stream); + zip->compress_stream = mz_stream_zlib_create(); #endif #ifdef HAVE_BZIP2 else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_BZIP2) - mz_stream_bzip_create(&zip->compress_stream); + zip->compress_stream = mz_stream_bzip_create(); #endif #ifdef HAVE_LIBCOMP else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_DEFLATE || zip->file_info.compression_method == MZ_COMPRESS_METHOD_XZ) { - mz_stream_libcomp_create(&zip->compress_stream); - mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_COMPRESS_METHOD, - zip->file_info.compression_method); + zip->compress_stream = mz_stream_libcomp_create(); + if (zip->compress_stream) + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_COMPRESS_METHOD, + zip->file_info.compression_method); } #endif #ifdef HAVE_LZMA else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_LZMA || zip->file_info.compression_method == MZ_COMPRESS_METHOD_XZ) { - mz_stream_lzma_create(&zip->compress_stream); - mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_COMPRESS_METHOD, - zip->file_info.compression_method); + zip->compress_stream = mz_stream_lzma_create(); + if (zip->compress_stream) + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_COMPRESS_METHOD, + zip->file_info.compression_method); } #endif #ifdef HAVE_ZSTD else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_ZSTD) - mz_stream_zstd_create(&zip->compress_stream); + zip->compress_stream = mz_stream_zstd_create(); #endif else err = MZ_PARAM_ERROR; } + if (err == MZ_OK && !zip->compress_stream) + err = MZ_MEM_ERROR; + if (err == MZ_OK) { if (zip->open_mode & MZ_OPEN_MODE_WRITE) { mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_COMPRESS_LEVEL, compress_level); @@ -1981,8 +2005,8 @@ int32_t mz_zip_entry_write_open(void *handle, const mz_zip_file *file_info, int1 zip->file_info.pk_verify = mz_zip_get_pk_verify(dos_date, zip->file_info.crc, zip->file_info.flag); #endif #ifdef HAVE_WZAES - if (zip->file_info.aes_version && zip->file_info.aes_encryption_mode == 0) - zip->file_info.aes_encryption_mode = MZ_AES_ENCRYPTION_MODE_256; + if (zip->file_info.aes_version && zip->file_info.aes_strength == 0) + zip->file_info.aes_strength = MZ_AES_STRENGTH_256; #endif } @@ -2179,9 +2203,8 @@ int32_t mz_zip_entry_write_close(void *handle, uint32_t crc32, int64_t compresse if (err == MZ_OK) { /* Seek to crc32 and sizes offset in local header */ - err = mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, zip->file_info.disk_number); - if (err == MZ_OK) - err = mz_stream_seek(zip->stream, zip->file_info.disk_offset + MZ_ZIP_OFFSET_CRC_SIZES, MZ_SEEK_SET); + mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, zip->file_info.disk_number); + err = mz_stream_seek(zip->stream, zip->file_info.disk_offset + MZ_ZIP_OFFSET_CRC_SIZES, MZ_SEEK_SET); } if (err == MZ_OK) @@ -2600,13 +2623,13 @@ int32_t mz_zip_extrafield_contains(const uint8_t *extrafield, int32_t extrafield if (!extrafield || !extrafield_size) return MZ_PARAM_ERROR; - mz_stream_mem_create(&file_extra_stream); + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + mz_stream_mem_set_buffer(file_extra_stream, (void *)extrafield, extrafield_size); - err = mz_zip_extrafield_find(file_extra_stream, type, extrafield_size, length); - mz_stream_mem_delete(&file_extra_stream); - return err; } diff --git a/SSZipArchive/minizip/mz_zip.h b/SSZipArchive/minizip/mz_zip.h index 65be301..cc01ee5 100644 --- a/SSZipArchive/minizip/mz_zip.h +++ b/SSZipArchive/minizip/mz_zip.h @@ -48,7 +48,7 @@ typedef struct mz_zip_file_s { uint16_t zip64; /* zip64 extension mode */ uint16_t aes_version; /* winzip aes extension if not 0 */ - uint8_t aes_encryption_mode; /* winzip aes encryption mode */ + uint8_t aes_strength; /* winzip aes encryption strength */ uint16_t pk_verify; /* pkware encryption verifier */ } mz_zip_file, mz_zip_entry; @@ -59,7 +59,7 @@ typedef int32_t (*mz_zip_locate_entry_cb)(void *handle, void *userdata, mz_zip_f /***************************************************************************/ -void * mz_zip_create(void **handle); +void * mz_zip_create(void); /* Create zip instance for opening */ void mz_zip_delete(void **handle); diff --git a/SSZipArchive/minizip/mz_zip_rw.c b/SSZipArchive/minizip/mz_zip_rw.c index 05390cc..d7c60b5 100644 --- a/SSZipArchive/minizip/mz_zip_rw.c +++ b/SSZipArchive/minizip/mz_zip_rw.c @@ -83,7 +83,10 @@ int32_t mz_zip_reader_open(void *handle, void *stream) { reader->cd_verified = 0; reader->cd_zipped = 0; - mz_zip_create(&reader->zip_handle); + reader->zip_handle = mz_zip_create(); + if (!reader->zip_handle) + return MZ_MEM_ERROR; + mz_zip_set_recover(reader->zip_handle, reader->recover); err = mz_zip_open(reader->zip_handle, stream, MZ_OPEN_MODE_READ); @@ -103,9 +106,22 @@ int32_t mz_zip_reader_open_file(void *handle, const char *path) { mz_zip_reader_close(handle); - mz_stream_os_create(&reader->file_stream); - mz_stream_buffered_create(&reader->buffered_stream); - mz_stream_split_create(&reader->split_stream); + reader->file_stream = mz_stream_os_create(); + if (!reader->file_stream) + return MZ_MEM_ERROR; + + reader->buffered_stream = mz_stream_buffered_create(); + if (!reader->buffered_stream) { + mz_stream_os_delete(&reader->file_stream); + return MZ_MEM_ERROR; + } + + reader->split_stream = mz_stream_split_create(); + if (!reader->split_stream) { + mz_stream_os_delete(&reader->file_stream); + mz_stream_buffered_delete(&reader->buffered_stream); + return MZ_MEM_ERROR; + } mz_stream_set_base(reader->buffered_stream, reader->file_stream); mz_stream_set_base(reader->split_stream, reader->buffered_stream); @@ -124,7 +140,9 @@ int32_t mz_zip_reader_open_file_in_memory(void *handle, const char *path) { mz_zip_reader_close(handle); - mz_stream_os_create(&file_stream); + file_stream = mz_stream_os_create(); + if (!file_stream) + return MZ_MEM_ERROR; err = mz_stream_os_open(file_stream, path, MZ_OPEN_MODE_READ); @@ -138,7 +156,9 @@ int32_t mz_zip_reader_open_file_in_memory(void *handle, const char *path) { file_size = mz_stream_os_tell(file_stream); mz_stream_os_seek(file_stream, 0, MZ_SEEK_SET); - if ((file_size <= 0) || (file_size > UINT32_MAX)) { + reader->mem_stream = mz_stream_mem_create(); + + if ((file_size <= 0) || (file_size > UINT32_MAX) || (!reader->mem_stream)) { /* Memory size is too large or too small */ mz_stream_os_close(file_stream); @@ -147,7 +167,6 @@ int32_t mz_zip_reader_open_file_in_memory(void *handle, const char *path) { return MZ_MEM_ERROR; } - mz_stream_mem_create(&reader->mem_stream); mz_stream_mem_set_grow_size(reader->mem_stream, (int32_t)file_size); mz_stream_mem_open(reader->mem_stream, NULL, MZ_OPEN_MODE_CREATE); @@ -170,7 +189,9 @@ int32_t mz_zip_reader_open_buffer(void *handle, uint8_t *buf, int32_t len, uint8 mz_zip_reader_close(handle); - mz_stream_mem_create(&reader->mem_stream); + reader->mem_stream = mz_stream_mem_create(); + if (!reader->mem_stream) + return MZ_MEM_ERROR; if (copy) { mz_stream_mem_set_grow_size(reader->mem_stream, len); @@ -241,7 +262,10 @@ int32_t mz_zip_reader_unzip_cd(void *handle) { if (err != MZ_OK) return err; - mz_stream_mem_create(&file_extra_stream); + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + mz_stream_mem_set_buffer(file_extra_stream, (void *)cd_info->extrafield, cd_info->extrafield_size); err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_CDCD, INT32_MAX, NULL); @@ -382,26 +406,19 @@ int32_t mz_zip_reader_entry_open(void *handle) { return err; if (mz_zip_reader_entry_get_first_hash(handle, &reader->hash_algorithm, &reader->hash_digest_size) == MZ_OK) { - mz_crypt_sha_create(&reader->hash); + reader->hash = mz_crypt_sha_create(); + if (!reader->hash) + return MZ_MEM_ERROR; + if (reader->hash_algorithm == MZ_HASH_SHA1) - mz_crypt_sha_set_algorithm(reader->hash, MZ_HASH_SHA1); + err = mz_crypt_sha_set_algorithm(reader->hash, MZ_HASH_SHA1); else if (reader->hash_algorithm == MZ_HASH_SHA256) - mz_crypt_sha_set_algorithm(reader->hash, MZ_HASH_SHA256); + err = mz_crypt_sha_set_algorithm(reader->hash, MZ_HASH_SHA256); else err = MZ_SUPPORT_ERROR; if (err == MZ_OK) mz_crypt_sha_begin(reader->hash); -#ifdef MZ_ZIP_SIGNING - if (err == MZ_OK) { - if (mz_zip_reader_entry_has_sign(handle) == MZ_OK) { - err = mz_zip_reader_entry_sign_verify(handle); - if (err == MZ_OK) - reader->entry_verified = 1; - } else if (reader->sign_required && !reader->cd_verified) - err = MZ_SIGN_ERROR; - } -#endif } else if (reader->sign_required && !reader->cd_verified) err = MZ_SIGN_ERROR; #endif @@ -450,58 +467,6 @@ int32_t mz_zip_reader_entry_read(void *handle, void *buf, int32_t len) { return read; } -int32_t mz_zip_reader_entry_has_sign(void *handle) { - mz_zip_reader *reader = (mz_zip_reader *)handle; - - if (!reader || mz_zip_entry_is_open(reader->zip_handle) != MZ_OK) - return MZ_PARAM_ERROR; - - return mz_zip_extrafield_contains(reader->file_info->extrafield, - reader->file_info->extrafield_size, MZ_ZIP_EXTENSION_SIGN, NULL); -} - -#if !defined(MZ_ZIP_NO_CRYPTO) && defined(MZ_ZIP_SIGNING) -int32_t mz_zip_reader_entry_sign_verify(void *handle) { - mz_zip_reader *reader = (mz_zip_reader *)handle; - void *file_extra_stream = NULL; - int32_t err = MZ_OK; - uint8_t *signature = NULL; - uint16_t signature_size = 0; - uint8_t hash[MZ_HASH_MAX_SIZE]; - - if (!reader || mz_zip_entry_is_open(reader->zip_handle) != MZ_OK) - return MZ_PARAM_ERROR; - - mz_stream_mem_create(&file_extra_stream); - mz_stream_mem_set_buffer(file_extra_stream, (void *)reader->file_info->extrafield, - reader->file_info->extrafield_size); - - err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_SIGN, INT32_MAX, &signature_size); - if ((err == MZ_OK) && (signature_size > 0)) { - signature = (uint8_t *)malloc(signature_size); - if (mz_stream_read(file_extra_stream, signature, signature_size) != signature_size) - err = MZ_READ_ERROR; - } - - mz_stream_mem_delete(&file_extra_stream); - - if (err == MZ_OK) { - /* Get most secure hash to verify signature against */ - err = mz_zip_reader_entry_get_hash(handle, reader->hash_algorithm, hash, reader->hash_digest_size); - } - - if (err == MZ_OK) { - /* Verify the pkcs signature */ - err = mz_crypt_sign_verify(hash, reader->hash_digest_size, signature, signature_size); - } - - if (signature) - free(signature); - - return err; -} -#endif - int32_t mz_zip_reader_entry_get_hash(void *handle, uint16_t algorithm, uint8_t *digest, int32_t digest_size) { mz_zip_reader *reader = (mz_zip_reader *)handle; void *file_extra_stream = NULL; @@ -510,7 +475,10 @@ int32_t mz_zip_reader_entry_get_hash(void *handle, uint16_t algorithm, uint8_t * uint16_t cur_algorithm = 0; uint16_t cur_digest_size = 0; - mz_stream_mem_create(&file_extra_stream); + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + mz_stream_mem_set_buffer(file_extra_stream, (void *)reader->file_info->extrafield, reader->file_info->extrafield_size); @@ -548,7 +516,10 @@ int32_t mz_zip_reader_entry_get_first_hash(void *handle, uint16_t *algorithm, ui if (!reader || !algorithm) return MZ_PARAM_ERROR; - mz_stream_mem_create(&file_extra_stream); + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + mz_stream_mem_set_buffer(file_extra_stream, (void *)reader->file_info->extrafield, reader->file_info->extrafield_size); @@ -679,38 +650,45 @@ int32_t mz_zip_reader_entry_save_file(void *handle, const char *path) { int32_t err_attrib = 0; int32_t err = MZ_OK; int32_t err_cb = MZ_OK; - char pathwfs[512]; - char directory[512]; + size_t path_length = 0; + char *pathwfs = NULL; + char *directory = NULL; if (mz_zip_reader_is_open(reader) != MZ_OK) return MZ_PARAM_ERROR; if (!reader->file_info || !path) return MZ_PARAM_ERROR; + path_length = strlen(path); + /* Convert to forward slashes for unix which doesn't like backslashes */ - strncpy(pathwfs, path, sizeof(pathwfs) - 1); - pathwfs[sizeof(pathwfs) - 1] = 0; + pathwfs = (char *)calloc(path_length + 1, sizeof(char)); + if (!pathwfs) + return MZ_MEM_ERROR; + strncat(pathwfs, path, path_length); mz_path_convert_slashes(pathwfs, MZ_PATH_SLASH_UNIX); if (reader->entry_cb) reader->entry_cb(handle, reader->entry_userdata, reader->file_info, pathwfs); - strncpy(directory, pathwfs, sizeof(directory) - 1); - directory[sizeof(directory) - 1] = 0; + directory = (char *)calloc(path_length + 1, sizeof(char)); + if (!directory) + return MZ_MEM_ERROR; + strncat(directory, pathwfs, path_length); mz_path_remove_filename(directory); /* If it is a directory entry then create a directory instead of writing file */ if ((mz_zip_entry_is_dir(reader->zip_handle) == MZ_OK) && (mz_zip_entry_is_symlink(reader->zip_handle) != MZ_OK)) { err = mz_dir_make(directory); - return err; + goto save_cleanup; } /* Check if file exists and ask if we want to overwrite */ if (reader->overwrite_cb && mz_os_file_exists(pathwfs) == MZ_OK) { err_cb = reader->overwrite_cb(handle, reader->overwrite_userdata, reader->file_info, pathwfs); if (err_cb != MZ_OK) - return err; + goto save_cleanup; /* We want to overwrite the file so we delete the existing one */ mz_os_unlink(pathwfs); } @@ -726,7 +704,7 @@ int32_t mz_zip_reader_entry_save_file(void *handle, const char *path) { if (mz_os_is_dir(directory) != MZ_OK) { err = mz_dir_make(directory); if (err != MZ_OK) - return err; + goto save_cleanup; } /* If it is a symbolic link then create symbolic link instead of writing file */ @@ -736,7 +714,12 @@ int32_t mz_zip_reader_entry_save_file(void *handle, const char *path) { err = mz_os_make_symlink(pathwfs, reader->file_info->linkname); } else if (reader->file_info->uncompressed_size < UINT16_MAX) { /* Create symbolic link from zip entry contents */ - mz_stream_mem_create(&stream); + stream = mz_stream_mem_create(); + if (!stream) { + err = MZ_MEM_ERROR; + goto save_cleanup; + } + err = mz_stream_mem_open(stream, NULL, MZ_OPEN_MODE_CREATE); if (err == MZ_OK) @@ -756,11 +739,16 @@ int32_t mz_zip_reader_entry_save_file(void *handle, const char *path) { } /* Don't check return value because we aren't validating symbolic link target */ - return err; + goto save_cleanup; } /* Create the file on disk so we can save to it */ - mz_stream_os_create(&stream); + stream = mz_stream_os_create(); + if (!stream) { + err = MZ_MEM_ERROR; + goto save_cleanup; + } + err = mz_stream_os_open(stream, pathwfs, MZ_OPEN_MODE_CREATE); if (err == MZ_OK) @@ -784,6 +772,10 @@ int32_t mz_zip_reader_entry_save_file(void *handle, const char *path) { mz_os_set_file_attribs(pathwfs, target_attrib); } +save_cleanup: + free(pathwfs); + free(directory); + return err; } @@ -800,7 +792,10 @@ int32_t mz_zip_reader_entry_save_buffer(void *handle, void *buf, int32_t len) { return MZ_BUF_ERROR; /* Create a memory stream backed by our buffer and save to it */ - mz_stream_mem_create(&mem_stream); + mem_stream = mz_stream_mem_create(); + if (!mem_stream) + return MZ_MEM_ERROR; + mz_stream_mem_set_buffer(mem_stream, buf, len); err = mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_READ); @@ -828,10 +823,13 @@ int32_t mz_zip_reader_entry_save_buffer_length(void *handle) { int32_t mz_zip_reader_save_all(void *handle, const char *destination_dir) { mz_zip_reader *reader = (mz_zip_reader *)handle; int32_t err = MZ_OK; - uint8_t *utf8_string = NULL; - char path[512]; - char utf8_name[256]; - char resolved_name[256]; + int32_t utf8_name_size = 0; + int32_t resolved_name_size = 0; + char *utf8_string = NULL; + char *path = NULL; + char *utf8_name = NULL; + char *resolved_name = NULL; + char* new_alloc = NULL; err = mz_zip_reader_goto_first_entry(handle); @@ -839,29 +837,57 @@ int32_t mz_zip_reader_save_all(void *handle, const char *destination_dir) { return err; while (err == MZ_OK) { + /* Assume 4 bytes per character needed + 1 for terminating null */ + utf8_name_size = reader->file_info->filename_size * 4 + 1; + resolved_name_size = utf8_name_size; + + if (destination_dir) { + /* +1 is for the "/" separator */ + resolved_name_size += (int)strlen(destination_dir) + 1; + } + + new_alloc = (char *)realloc(path, resolved_name_size); + if (!new_alloc) { + err = MZ_MEM_ERROR; + goto save_all_cleanup; + } + path = new_alloc; + new_alloc = (char *)realloc(utf8_name, utf8_name_size); + if (!new_alloc) { + err = MZ_MEM_ERROR; + goto save_all_cleanup; + } + utf8_name = new_alloc; + new_alloc = (char *)realloc(resolved_name, resolved_name_size); + if ( !new_alloc) { + err = MZ_MEM_ERROR; + goto save_all_cleanup; + } + resolved_name = new_alloc; + /* Construct output path */ path[0] = 0; - strncpy(utf8_name, reader->file_info->filename, sizeof(utf8_name) - 1); - utf8_name[sizeof(utf8_name) - 1] = 0; + strncpy(utf8_name, reader->file_info->filename, utf8_name_size - 1); + utf8_name[utf8_name_size - 1] = 0; if ((reader->encoding > 0) && (reader->file_info->flag & MZ_ZIP_FLAG_UTF8) == 0) { utf8_string = mz_os_utf8_string_create(reader->file_info->filename, reader->encoding); if (utf8_string) { - strncpy(utf8_name, (char *)utf8_string, sizeof(utf8_name) - 1); - utf8_name[sizeof(utf8_name) - 1] = 0; + strncpy(utf8_name, (char *)utf8_string, utf8_name_size - 1); + utf8_name[utf8_name_size - 1] = 0; mz_os_utf8_string_delete(&utf8_string); } } - err = mz_path_resolve(utf8_name, resolved_name, sizeof(resolved_name)); + err = mz_path_resolve(utf8_name, resolved_name, resolved_name_size); if (err != MZ_OK) break; if (destination_dir) - mz_path_combine(path, destination_dir, sizeof(path)); + mz_path_combine(path, destination_dir, resolved_name_size); - mz_path_combine(path, resolved_name, sizeof(path)); + mz_path_combine(path, resolved_name, resolved_name_size); /* Save file to disk */ err = mz_zip_reader_entry_save_file(handle, path); @@ -871,7 +897,12 @@ int32_t mz_zip_reader_save_all(void *handle, const char *destination_dir) { } if (err == MZ_END_OF_LIST) - return MZ_OK; + err = MZ_OK; + +save_all_cleanup: + free(path); + free(utf8_name); + free(resolved_name); return err; } @@ -932,11 +963,6 @@ void mz_zip_reader_set_encoding(void *handle, int32_t encoding) { reader->encoding = encoding; } -void mz_zip_reader_set_sign_required(void *handle, uint8_t sign_required) { - mz_zip_reader *reader = (mz_zip_reader *)handle; - reader->sign_required = sign_required; -} - void mz_zip_reader_set_overwrite_cb(void *handle, void *userdata, mz_zip_reader_overwrite_cb cb) { mz_zip_reader *reader = (mz_zip_reader *)handle; reader->overwrite_cb = cb; @@ -978,17 +1004,12 @@ int32_t mz_zip_reader_get_zip_handle(void *handle, void **zip_handle) { /***************************************************************************/ -void *mz_zip_reader_create(void **handle) { - mz_zip_reader *reader = NULL; - - reader = (mz_zip_reader *)calloc(1, sizeof(mz_zip_reader)); +void *mz_zip_reader_create(void) { + mz_zip_reader *reader = (mz_zip_reader *)calloc(1, sizeof(mz_zip_reader)); if (reader) { reader->recover = 1; reader->progress_cb_interval_ms = MZ_DEFAULT_PROGRESS_INTERVAL; } - if (handle) - *handle = reader; - return reader; } @@ -1011,7 +1032,8 @@ typedef struct mz_zip_writer_s { void *file_stream; void *buffered_stream; void *split_stream; - void *sha256; + void *hash; + uint16_t hash_algorithm; void *mem_stream; void *file_extra_stream; mz_zip_file file_info; @@ -1030,9 +1052,6 @@ typedef struct mz_zip_writer_s { entry_cb; const char *password; const char *comment; - uint8_t *cert_data; - int32_t cert_data_size; - const char *cert_pwd; uint16_t compress_method; int16_t compress_level; uint8_t follow_links; @@ -1073,7 +1092,10 @@ int32_t mz_zip_writer_zip_cd(void *handle) { if (writer->password) cd_file.flag |= MZ_ZIP_FLAG_ENCRYPTED; - mz_stream_mem_create(&file_extra_stream); + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + mz_stream_mem_open(file_extra_stream, NULL, MZ_OPEN_MODE_CREATE); mz_zip_extrafield_write(file_extra_stream, MZ_ZIP_EXTENSION_CDCD, 8); @@ -1113,7 +1135,10 @@ static int32_t mz_zip_writer_open_int(void *handle, void *stream, int32_t mode) mz_zip_writer *writer = (mz_zip_writer *)handle; int32_t err = MZ_OK; - mz_zip_create(&writer->zip_handle); + writer->zip_handle = mz_zip_create(); + if (writer->zip_handle == NULL) + return MZ_MEM_ERROR; + err = mz_zip_open(writer->zip_handle, stream, mode); if (err != MZ_OK) { @@ -1172,9 +1197,20 @@ int32_t mz_zip_writer_open_file(void *handle, const char *path, int64_t disk_siz mode |= MZ_OPEN_MODE_APPEND; } - mz_stream_os_create(&writer->file_stream); - mz_stream_buffered_create(&writer->buffered_stream); - mz_stream_split_create(&writer->split_stream); + writer->file_stream = mz_stream_os_create(); + if (!writer->file_stream) + return MZ_MEM_ERROR; + writer->buffered_stream = mz_stream_buffered_create(); + if (!writer->buffered_stream) { + mz_stream_os_delete(&writer->file_stream); + return MZ_MEM_ERROR; + } + writer->split_stream = mz_stream_split_create(); + if (!writer->split_stream) { + mz_stream_buffered_delete(&writer->buffered_stream); + mz_stream_os_delete(&writer->file_stream); + return MZ_MEM_ERROR; + } mz_stream_set_base(writer->buffered_stream, writer->file_stream); mz_stream_set_base(writer->split_stream, writer->buffered_stream); @@ -1196,7 +1232,9 @@ int32_t mz_zip_writer_open_file_in_memory(void *handle, const char *path) { mz_zip_writer_close(handle); - mz_stream_os_create(&file_stream); + file_stream = mz_stream_os_create(); + if (!file_stream) + return MZ_MEM_ERROR; err = mz_stream_os_open(file_stream, path, MZ_OPEN_MODE_READ); @@ -1209,8 +1247,9 @@ int32_t mz_zip_writer_open_file_in_memory(void *handle, const char *path) { mz_stream_os_seek(file_stream, 0, MZ_SEEK_END); file_size = mz_stream_os_tell(file_stream); mz_stream_os_seek(file_stream, 0, MZ_SEEK_SET); + writer->mem_stream = mz_stream_mem_create(); - if ((file_size <= 0) || (file_size > UINT32_MAX)) { + if ((file_size <= 0) || (file_size > UINT32_MAX) || (!writer->mem_stream)) { /* Memory size is too large or too small */ mz_stream_os_close(file_stream); @@ -1219,7 +1258,6 @@ int32_t mz_zip_writer_open_file_in_memory(void *handle, const char *path) { return MZ_MEM_ERROR; } - mz_stream_mem_create(&writer->mem_stream); mz_stream_mem_set_grow_size(writer->mem_stream, (int32_t)file_size); mz_stream_mem_open(writer->mem_stream, NULL, MZ_OPEN_MODE_CREATE); @@ -1295,10 +1333,18 @@ int32_t mz_zip_writer_entry_open(void *handle, mz_zip_file *file_info) { #ifndef MZ_ZIP_NO_CRYPTO if (mz_zip_attrib_is_dir(writer->file_info.external_fa, writer->file_info.version_madeby) != MZ_OK) { - /* Start calculating sha256 */ - mz_crypt_sha_create(&writer->sha256); - mz_crypt_sha_set_algorithm(writer->sha256, MZ_HASH_SHA256); - mz_crypt_sha_begin(writer->sha256); + /* Start calculating hash */ + writer->hash = mz_crypt_sha_create(); + writer->hash_algorithm = MZ_HASH_SHA256; + if (!writer->hash) + return MZ_MEM_ERROR; + err = mz_crypt_sha_set_algorithm(writer->hash, writer->hash_algorithm); + if (err != MZ_OK) { + writer->hash_algorithm = MZ_HASH_SHA1; + err = mz_crypt_sha_set_algorithm(writer->hash, writer->hash_algorithm); + } + + mz_crypt_sha_begin(writer->hash); } #endif @@ -1309,40 +1355,6 @@ int32_t mz_zip_writer_entry_open(void *handle, mz_zip_file *file_info) { return err; } -#if !defined(MZ_ZIP_NO_CRYPTO) && defined(MZ_ZIP_SIGNING) -int32_t mz_zip_writer_entry_sign(void *handle, uint8_t *message, int32_t message_size, - uint8_t *cert_data, int32_t cert_data_size, const char *cert_pwd) { - mz_zip_writer *writer = (mz_zip_writer *)handle; - int32_t err = MZ_OK; - int32_t signature_size = 0; - uint8_t *signature = NULL; - - if (!writer || !cert_data || cert_data_size <= 0) - return MZ_PARAM_ERROR; - if (mz_zip_entry_is_open(writer->zip_handle) != MZ_OK) - return MZ_PARAM_ERROR; - - /* Sign message with certificate */ - err = mz_crypt_sign(message, message_size, cert_data, cert_data_size, cert_pwd, - &signature, &signature_size); - - if (err == MZ_OK && signature) { - /* Write signature zip extra field */ - err = mz_zip_extrafield_write(writer->file_extra_stream, MZ_ZIP_EXTENSION_SIGN, - (uint16_t)signature_size); - - if (err == MZ_OK) { - if (mz_stream_write(writer->file_extra_stream, signature, signature_size) != signature_size) - err = MZ_WRITE_ERROR; - } - - free(signature); - } - - return err; -} -#endif - int32_t mz_zip_writer_entry_close(void *handle) { mz_zip_writer *writer = (mz_zip_writer *)handle; int32_t err = MZ_OK; @@ -1350,38 +1362,44 @@ int32_t mz_zip_writer_entry_close(void *handle) { const uint8_t *extrafield = NULL; int32_t extrafield_size = 0; int16_t field_length_hash = 0; - uint8_t sha256[MZ_HASH_SHA256_SIZE]; + uint8_t hash_digest[MZ_HASH_MAX_SIZE]; - if (writer->sha256) { - mz_crypt_sha_end(writer->sha256, sha256, sizeof(sha256)); - mz_crypt_sha_delete(&writer->sha256); + if (writer->hash) { + uint16_t hash_digest_size = 0; + + switch (writer->hash_algorithm) { + case MZ_HASH_SHA1: + hash_digest_size = MZ_HASH_SHA1_SIZE; + break; + case MZ_HASH_SHA256: + hash_digest_size = MZ_HASH_SHA256_SIZE; + break; + default: + return MZ_PARAM_ERROR; + } + + mz_crypt_sha_end(writer->hash, hash_digest, hash_digest_size); + mz_crypt_sha_delete(&writer->hash); /* Copy extrafield so we can append our own fields before close */ - mz_stream_mem_create(&writer->file_extra_stream); + writer->file_extra_stream = mz_stream_mem_create(); + if (!writer->file_extra_stream) + return MZ_MEM_ERROR; + mz_stream_mem_open(writer->file_extra_stream, NULL, MZ_OPEN_MODE_CREATE); - /* Write sha256 hash to extrafield */ - field_length_hash = 4 + MZ_HASH_SHA256_SIZE; + /* Write digest to extrafield */ + field_length_hash = 4 + hash_digest_size; err = mz_zip_extrafield_write(writer->file_extra_stream, MZ_ZIP_EXTENSION_HASH, field_length_hash); if (err == MZ_OK) - err = mz_stream_write_uint16(writer->file_extra_stream, MZ_HASH_SHA256); + err = mz_stream_write_uint16(writer->file_extra_stream, writer->hash_algorithm); if (err == MZ_OK) - err = mz_stream_write_uint16(writer->file_extra_stream, MZ_HASH_SHA256_SIZE); + err = mz_stream_write_uint16(writer->file_extra_stream, hash_digest_size); if (err == MZ_OK) { - if (mz_stream_write(writer->file_extra_stream, sha256, sizeof(sha256)) != MZ_HASH_SHA256_SIZE) + if (mz_stream_write(writer->file_extra_stream, hash_digest, hash_digest_size) != hash_digest_size) err = MZ_WRITE_ERROR; } -#ifdef MZ_ZIP_SIGNING - if ((err == MZ_OK) && (writer->cert_data) && (writer->cert_data_size > 0)) { - /* Sign entry if not zipping cd or if it is cd being zipped */ - if (!writer->zip_cd || strcmp(writer->file_info.filename, MZ_ZIP_CD_FILENAME) == 0) { - err = mz_zip_writer_entry_sign(handle, sha256, sizeof(sha256), - writer->cert_data, writer->cert_data_size, writer->cert_pwd); - } - } -#endif - if ((writer->file_info.extrafield) && (writer->file_info.extrafield_size > 0)) mz_stream_mem_write(writer->file_extra_stream, writer->file_info.extrafield, writer->file_info.extrafield_size); @@ -1413,8 +1431,8 @@ int32_t mz_zip_writer_entry_write(void *handle, const void *buf, int32_t len) { int32_t written = 0; written = mz_zip_entry_write(writer->zip_handle, buf, len); #ifndef MZ_ZIP_NO_CRYPTO - if (written > 0 && writer->sha256) - mz_crypt_sha_update(writer->sha256, buf, written); + if (written > 0 && writer->hash) + mz_crypt_sha_update(writer->hash, buf, written); #endif return written; } @@ -1527,7 +1545,10 @@ int32_t mz_zip_writer_add_buffer(void *handle, void *buf, int32_t len, mz_zip_fi return MZ_PARAM_ERROR; /* Create a memory stream backed by our buffer and add from it */ - mz_stream_mem_create(&mem_stream); + mem_stream = mz_stream_mem_create(); + if (!mem_stream) + return MZ_STREAM_ERROR; + mz_stream_mem_set_buffer(mem_stream, buf, len); err = mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_READ); @@ -1601,7 +1622,9 @@ int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filen if (err == MZ_OK) file_info.linkname = link_path; } else if (mz_os_is_dir(path) != MZ_OK) { - mz_stream_os_create(&stream); + stream = mz_stream_os_create(); + if (!stream) + return MZ_STREAM_ERROR; err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ); } @@ -1749,6 +1772,10 @@ int32_t mz_zip_writer_copy_from_reader(void *handle, void *reader) { if (mz_zip_entry_is_open(writer_zip_handle) == MZ_OK) mz_zip_entry_close(writer_zip_handle); +#ifndef MZ_ZIP_NO_CRYPTO + mz_crypt_sha_delete(&writer->hash); +#endif + writer->raw = original_raw; } @@ -1810,49 +1837,6 @@ void mz_zip_writer_set_zip_cd(void *handle, uint8_t zip_cd) { writer->zip_cd = zip_cd; } -int32_t mz_zip_writer_set_certificate(void *handle, const char *cert_path, const char *cert_pwd) { - mz_zip_writer *writer = (mz_zip_writer *)handle; - void *cert_stream = NULL; - uint8_t *cert_data = NULL; - int32_t cert_data_size = 0; - int32_t err = MZ_OK; - - if (!cert_path) - return MZ_PARAM_ERROR; - - cert_data_size = (int32_t)mz_os_get_file_size(cert_path); - - if (cert_data_size == 0) - return MZ_PARAM_ERROR; - - if (writer->cert_data) { - free(writer->cert_data); - writer->cert_data = NULL; - } - - cert_data = (uint8_t *)malloc(cert_data_size); - - /* Read pkcs12 certificate from disk */ - mz_stream_os_create(&cert_stream); - err = mz_stream_os_open(cert_stream, cert_path, MZ_OPEN_MODE_READ); - if (err == MZ_OK) { - if (mz_stream_os_read(cert_stream, cert_data, cert_data_size) != cert_data_size) - err = MZ_READ_ERROR; - mz_stream_os_close(cert_stream); - } - mz_stream_os_delete(&cert_stream); - - if (err == MZ_OK) { - writer->cert_data = cert_data; - writer->cert_data_size = cert_data_size; - writer->cert_pwd = cert_pwd; - } else { - free(cert_data); - } - - return err; -} - void mz_zip_writer_set_overwrite_cb(void *handle, void *userdata, mz_zip_writer_overwrite_cb cb) { mz_zip_writer *writer = (mz_zip_writer *)handle; writer->overwrite_cb = cb; @@ -1894,10 +1878,8 @@ int32_t mz_zip_writer_get_zip_handle(void *handle, void **zip_handle) { /***************************************************************************/ -void *mz_zip_writer_create(void **handle) { - mz_zip_writer *writer = NULL; - - writer = (mz_zip_writer *)calloc(1, sizeof(mz_zip_writer)); +void *mz_zip_writer_create(void) { + mz_zip_writer *writer = (mz_zip_writer *)calloc(1, sizeof(mz_zip_writer)); if (writer) { #if defined(HAVE_WZAES) writer->aes = 1; @@ -1914,9 +1896,6 @@ void *mz_zip_writer_create(void **handle) { writer->compress_level = MZ_COMPRESS_LEVEL_BEST; writer->progress_cb_interval_ms = MZ_DEFAULT_PROGRESS_INTERVAL; } - if (handle) - *handle = writer; - return writer; } @@ -1927,13 +1906,6 @@ void mz_zip_writer_delete(void **handle) { writer = (mz_zip_writer *)*handle; if (writer) { mz_zip_writer_close(writer); - - if (writer->cert_data) - free(writer->cert_data); - - writer->cert_data = NULL; - writer->cert_data_size = 0; - free(writer); } *handle = NULL; diff --git a/SSZipArchive/minizip/mz_zip_rw.h b/SSZipArchive/minizip/mz_zip_rw.h index 195b507..71f267e 100644 --- a/SSZipArchive/minizip/mz_zip_rw.h +++ b/SSZipArchive/minizip/mz_zip_rw.h @@ -67,12 +67,6 @@ int32_t mz_zip_reader_entry_close(void *handle); int32_t mz_zip_reader_entry_read(void *handle, void *buf, int32_t len); /* Reads and entry after being opened */ -int32_t mz_zip_reader_entry_has_sign(void *handle); -/* Checks to see if the entry has a signature */ - -int32_t mz_zip_reader_entry_sign_verify(void *handle); -/* Verifies a signature stored with the entry */ - int32_t mz_zip_reader_entry_get_hash(void *handle, uint16_t algorithm, uint8_t *digest, int32_t digest_size); /* Gets a hash algorithm from the entry's extra field */ @@ -131,9 +125,6 @@ int32_t mz_zip_reader_set_recover(void *handle, uint8_t recover); void mz_zip_reader_set_encoding(void *handle, int32_t encoding); /* Sets whether or not it should support a special character encoding in zip file names. */ -void mz_zip_reader_set_sign_required(void *handle, uint8_t sign_required); -/* Sets whether or not it a signature is required */ - void mz_zip_reader_set_overwrite_cb(void *handle, void *userdata, mz_zip_reader_overwrite_cb cb); /* Callback for what to do when a file is being overwritten */ @@ -152,7 +143,7 @@ void mz_zip_reader_set_entry_cb(void *handle, void *userdata, mz_zip_reader_e int32_t mz_zip_reader_get_zip_handle(void *handle, void **zip_handle); /* Gets the underlying zip instance handle */ -void* mz_zip_reader_create(void **handle); +void* mz_zip_reader_create(void); /* Create new instance of zip reader */ void mz_zip_reader_delete(void **handle); @@ -270,7 +261,7 @@ void mz_zip_writer_set_entry_cb(void *handle, void *userdata, mz_zip_writer_e int32_t mz_zip_writer_get_zip_handle(void *handle, void **zip_handle); /* Gets the underlying zip handle */ -void* mz_zip_writer_create(void **handle); +void* mz_zip_writer_create(void); /* Create new instance of zip writer */ void mz_zip_writer_delete(void **handle); diff --git a/ZipArchive.xcodeproj/project.pbxproj b/ZipArchive.xcodeproj/project.pbxproj index adb07d8..1aafa1c 100644 --- a/ZipArchive.xcodeproj/project.pbxproj +++ b/ZipArchive.xcodeproj/project.pbxproj @@ -1029,6 +1029,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", HAVE_ARC4RANDOM_BUF, + HAVE_ICONV, HAVE_INTTYPES_H, HAVE_PKCRYPT, HAVE_STDINT_H, @@ -1091,6 +1092,7 @@ GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( HAVE_ARC4RANDOM_BUF, + HAVE_ICONV, HAVE_INTTYPES_H, HAVE_PKCRYPT, HAVE_STDINT_H,