diff --git a/vendor/stormlib-9/CMakeLists.txt b/vendor/stormlib-9/CMakeLists.txt index eada5f3..aa44367 100644 --- a/vendor/stormlib-9/CMakeLists.txt +++ b/vendor/stormlib-9/CMakeLists.txt @@ -40,6 +40,7 @@ set(TOMCRYPT_FILES src/libtomcrypt/src/hashes/hash_memory.c src/libtomcrypt/src/hashes/md5.c src/libtomcrypt/src/hashes/sha1.c + src/libtomcrypt/src/hashes/sha256.c src/libtomcrypt/src/math/ltm_desc.c src/libtomcrypt/src/math/multi.c src/libtomcrypt/src/math/rand_prime.c diff --git a/vendor/stormlib-9/src/DllMain.rc b/vendor/stormlib-9/src/DllMain.rc index 27f43e2..69b5cf0 100644 --- a/vendor/stormlib-9/src/DllMain.rc +++ b/vendor/stormlib-9/src/DllMain.rc @@ -16,10 +16,8 @@ // Neutral resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -#ifdef _WIN32 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #pragma code_page(1250) -#endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // @@ -27,8 +25,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 9,22,0,3 - PRODUCTVERSION 9,22,0,3 + FILEVERSION 9,25,0,3 + PRODUCTVERSION 9,25,0,3 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -45,12 +43,12 @@ BEGIN BEGIN VALUE "Comments", "http://www.zezula.net/mpq.html" VALUE "FileDescription", "StormLib library for reading Blizzard MPQ archives" - VALUE "FileVersion", "9, 22, 0, 3\0" + VALUE "FileVersion", "9.25.0.3" VALUE "InternalName", "StormLib" - VALUE "LegalCopyright", "Copyright (c) 2014 - 2020 Ladislav Zezula" + VALUE "LegalCopyright", "Copyright (c) 2014 - 2023 Ladislav Zezula" VALUE "OriginalFilename", "StormLib.dll" VALUE "ProductName", "StormLib" - VALUE "ProductVersion", "9, 22, 0, 3\0" + VALUE "ProductVersion", "9.25.0.3" END END BLOCK "VarFileInfo" @@ -64,13 +62,11 @@ END ///////////////////////////////////////////////////////////////////////////// -// Czech resources +// Czech (Czech Republic) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CSY) -#ifdef _WIN32 LANGUAGE LANG_CZECH, SUBLANG_DEFAULT #pragma code_page(1250) -#endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -78,26 +74,26 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT // TEXTINCLUDE // -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END -3 TEXTINCLUDE +3 TEXTINCLUDE BEGIN "\r\n" "\0" END -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN "resource.h\0" END #endif // APSTUDIO_INVOKED -#endif // Czech resources +#endif // Czech (Czech Republic) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/vendor/stormlib-9/src/LibTomCrypt.c b/vendor/stormlib-9/src/LibTomCrypt.c index 012f5e0..f77b604 100644 --- a/vendor/stormlib-9/src/LibTomCrypt.c +++ b/vendor/stormlib-9/src/LibTomCrypt.c @@ -8,6 +8,7 @@ #include "libtomcrypt/src/hashes/hash_memory.c" #include "libtomcrypt/src/hashes/md5.c" #include "libtomcrypt/src/hashes/sha1.c" +#include "libtomcrypt/src/hashes/sha256.c" #include "libtomcrypt/src/math/multi.c" #include "libtomcrypt/src/math/rand_prime.c" #include "libtomcrypt/src/misc/base64_decode.c" diff --git a/vendor/stormlib-9/src/SBaseCommon.cpp b/vendor/stormlib-9/src/SBaseCommon.cpp index 233ccb9..aa7ec9f 100644 --- a/vendor/stormlib-9/src/SBaseCommon.cpp +++ b/vendor/stormlib-9/src/SBaseCommon.cpp @@ -15,7 +15,7 @@ #include "StormLib.h" #include "StormCommon.h" -char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Ladislav Zezula 1998-2014"; +char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Ladislav Zezula 1998-2023"; //----------------------------------------------------------------------------- // Local variables @@ -244,8 +244,8 @@ void InitializeMpqCryptography() } // Also register both MD5 and SHA1 hash algorithms - register_hash(&md5_desc); register_hash(&sha1_desc); + register_hash(&md5_desc); // Use LibTomMath as support math library for LibTomCrypt ltc_mp = ltm_desc; @@ -403,7 +403,7 @@ DWORD GetDefaultSpecialFileFlags(DWORD dwFileSize, USHORT wFormatVersion) { // Fixed for format 1.0 if(wFormatVersion == MPQ_FORMAT_VERSION_1) - return MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY; + return MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | MPQ_FILE_KEY_V2; // Size-dependent for formats 2.0-4.0 return (dwFileSize > 0x4000) ? (MPQ_FILE_COMPRESS | MPQ_FILE_SECTOR_CRC) : (MPQ_FILE_COMPRESS | MPQ_FILE_SINGLE_UNIT); @@ -696,7 +696,7 @@ DWORD DecryptFileKey( dwFileKey = HashString(szFileName, MPQ_HASH_FILE_KEY); // Fix the key, if needed - if(dwFlags & MPQ_FILE_FIX_KEY) + if(dwFlags & MPQ_FILE_KEY_V2) dwFileKey = (dwFileKey + dwMpqPos) ^ dwFileSize; // Return the key @@ -999,18 +999,20 @@ void * LoadMpqTable( LPBYTE pbCompressed = NULL; LPBYTE pbMpqTable; LPBYTE pbToRead; - DWORD dwBytesToRead = dwCompressedSize; + DWORD dwBytesToRead = dwTableSize; DWORD dwErrCode = ERROR_SUCCESS; // Allocate the MPQ table pbMpqTable = pbToRead = STORM_ALLOC(BYTE, dwTableSize); if(pbMpqTable != NULL) { - // Check if the MPQ table is encrypted + // Check if the MPQ table is compressed if(dwCompressedSize < dwTableSize) { // Allocate temporary buffer for holding compressed data pbCompressed = pbToRead = STORM_ALLOC(BYTE, dwCompressedSize); + dwBytesToRead = dwCompressedSize; + if(pbCompressed == NULL) { STORM_FREE(pbMpqTable); @@ -1152,6 +1154,7 @@ DWORD AllocateSectorBuffer(TMPQFile * hf) DWORD AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile) { TMPQArchive * ha = hf->ha; + TPatchInfo * pPatchInfo; DWORD dwLength = sizeof(TPatchInfo); // The following conditions must be true @@ -1162,35 +1165,39 @@ __AllocateAndLoadPatchInfo: // Allocate space for patch header. Start with default size, // and if its size if bigger, then we reload them - hf->pPatchInfo = STORM_ALLOC(TPatchInfo, 1); - if(hf->pPatchInfo == NULL) + pPatchInfo = (TPatchInfo *)(STORM_ALLOC(BYTE, dwLength)); + if(pPatchInfo == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Do we have to load the patch header from the file ? if(bLoadFromFile) { // Load the patch header - if(!FileStream_Read(ha->pStream, &hf->RawFilePos, hf->pPatchInfo, dwLength)) + if(!FileStream_Read(ha->pStream, &hf->RawFilePos, pPatchInfo, dwLength)) { - // Free the patch info - STORM_FREE(hf->pPatchInfo); - hf->pPatchInfo = NULL; + STORM_FREE(pPatchInfo); return GetLastError(); } // Perform necessary swapping - hf->pPatchInfo->dwLength = BSWAP_INT32_UNSIGNED(hf->pPatchInfo->dwLength); - hf->pPatchInfo->dwFlags = BSWAP_INT32_UNSIGNED(hf->pPatchInfo->dwFlags); - hf->pPatchInfo->dwDataSize = BSWAP_INT32_UNSIGNED(hf->pPatchInfo->dwDataSize); + pPatchInfo->dwLength = BSWAP_INT32_UNSIGNED(pPatchInfo->dwLength); + pPatchInfo->dwFlags = BSWAP_INT32_UNSIGNED(pPatchInfo->dwFlags); + pPatchInfo->dwDataSize = BSWAP_INT32_UNSIGNED(pPatchInfo->dwDataSize); + + // Do nothing if the patch info is not valid + if(!(pPatchInfo->dwFlags & MPQ_PATCH_INFO_VALID)) + { + STORM_FREE(pPatchInfo); + return ERROR_FILE_CORRUPT; + } // Verify the size of the patch header // If it's not default size, we have to reload them - if(hf->pPatchInfo->dwLength > dwLength) + if(pPatchInfo->dwLength > dwLength) { // Free the patch info - dwLength = hf->pPatchInfo->dwLength; - STORM_FREE(hf->pPatchInfo); - hf->pPatchInfo = NULL; + dwLength = pPatchInfo->dwLength; + STORM_FREE(pPatchInfo); // If the length is out of all possible ranges, fail the operation if(dwLength > 0x400) @@ -1199,16 +1206,17 @@ __AllocateAndLoadPatchInfo: } // Patch file data size according to the patch header - hf->dwDataSize = hf->pPatchInfo->dwDataSize; + hf->dwDataSize = pPatchInfo->dwDataSize; } else { - memset(hf->pPatchInfo, 0, dwLength); + memset(pPatchInfo, 0, dwLength); + pPatchInfo->dwLength = dwLength; + pPatchInfo->dwFlags = MPQ_PATCH_INFO_VALID; } // Save the final length to the patch header - hf->pPatchInfo->dwLength = dwLength; - hf->pPatchInfo->dwFlags = 0x80000000; + hf->pPatchInfo = pPatchInfo; return ERROR_SUCCESS; } @@ -1888,10 +1896,10 @@ void ConvertUInt16Buffer(void * ptr, size_t length) uint32_t nElements = (uint32_t)(length / sizeof(uint16_t)); while(nElements-- > 0) - { - *buffer = SwapUInt16(*buffer); - buffer++; - } + { + *buffer = SwapUInt16(*buffer); + buffer++; + } } // Swaps array of unsigned 32-bit integers @@ -1900,11 +1908,11 @@ void ConvertUInt32Buffer(void * ptr, size_t length) uint32_t * buffer = (uint32_t *)ptr; uint32_t nElements = (uint32_t)(length / sizeof(uint32_t)); - while(nElements-- > 0) - { - *buffer = SwapUInt32(*buffer); - buffer++; - } + while(nElements-- > 0) + { + *buffer = SwapUInt32(*buffer); + buffer++; + } } // Swaps array of unsigned 64-bit integers @@ -1913,37 +1921,37 @@ void ConvertUInt64Buffer(void * ptr, size_t length) uint64_t * buffer = (uint64_t *)ptr; uint32_t nElements = (uint32_t)(length / sizeof(uint64_t)); - while(nElements-- > 0) - { - *buffer = SwapUInt64(*buffer); - buffer++; - } + while(nElements-- > 0) + { + *buffer = SwapUInt64(*buffer); + buffer++; + } } // Swaps the TMPQHeader structure void ConvertTMPQHeader(void *header, uint16_t version) { - TMPQHeader * theHeader = (TMPQHeader *)header; + TMPQHeader * theHeader = (TMPQHeader *)header; // Swap header part version 1 if(version >= MPQ_FORMAT_VERSION_1) { - theHeader->dwID = SwapUInt32(theHeader->dwID); - theHeader->dwHeaderSize = SwapUInt32(theHeader->dwHeaderSize); - theHeader->dwArchiveSize = SwapUInt32(theHeader->dwArchiveSize); - theHeader->wFormatVersion = SwapUInt16(theHeader->wFormatVersion); - theHeader->wSectorSize = SwapUInt16(theHeader->wSectorSize); - theHeader->dwHashTablePos = SwapUInt32(theHeader->dwHashTablePos); - theHeader->dwBlockTablePos = SwapUInt32(theHeader->dwBlockTablePos); - theHeader->dwHashTableSize = SwapUInt32(theHeader->dwHashTableSize); - theHeader->dwBlockTableSize = SwapUInt32(theHeader->dwBlockTableSize); + theHeader->dwID = SwapUInt32(theHeader->dwID); + theHeader->dwHeaderSize = SwapUInt32(theHeader->dwHeaderSize); + theHeader->dwArchiveSize = SwapUInt32(theHeader->dwArchiveSize); + theHeader->wFormatVersion = SwapUInt16(theHeader->wFormatVersion); + theHeader->wSectorSize = SwapUInt16(theHeader->wSectorSize); + theHeader->dwHashTablePos = SwapUInt32(theHeader->dwHashTablePos); + theHeader->dwBlockTablePos = SwapUInt32(theHeader->dwBlockTablePos); + theHeader->dwHashTableSize = SwapUInt32(theHeader->dwHashTableSize); + theHeader->dwBlockTableSize = SwapUInt32(theHeader->dwBlockTableSize); } - if(version >= MPQ_FORMAT_VERSION_2) - { - theHeader->HiBlockTablePos64 = SwapUInt64(theHeader->HiBlockTablePos64); + if(version >= MPQ_FORMAT_VERSION_2) + { + theHeader->HiBlockTablePos64 = SwapUInt64(theHeader->HiBlockTablePos64); theHeader->wHashTablePosHi = SwapUInt16(theHeader->wHashTablePosHi); - theHeader->wBlockTablePosHi = SwapUInt16(theHeader->wBlockTablePosHi); + theHeader->wBlockTablePosHi = SwapUInt16(theHeader->wBlockTablePosHi); } if(version >= MPQ_FORMAT_VERSION_3) @@ -1954,7 +1962,7 @@ void ConvertTMPQHeader(void *header, uint16_t version) } if(version >= MPQ_FORMAT_VERSION_4) - { + { theHeader->HashTableSize64 = SwapUInt64(theHeader->HashTableSize64); theHeader->BlockTableSize64 = SwapUInt64(theHeader->BlockTableSize64); theHeader->HiBlockTableSize64 = SwapUInt64(theHeader->HiBlockTableSize64); diff --git a/vendor/stormlib-9/src/SBaseFileTable.cpp b/vendor/stormlib-9/src/SBaseFileTable.cpp index 8cbb473..fa79ccb 100644 --- a/vendor/stormlib-9/src/SBaseFileTable.cpp +++ b/vendor/stormlib-9/src/SBaseFileTable.cpp @@ -312,34 +312,38 @@ static ULONGLONG DetermineArchiveSize_V1( return (EndOfMpq - MpqOffset); } -static ULONGLONG DetermineArchiveSize_V2( - TMPQHeader * pHeader, - ULONGLONG MpqOffset, - ULONGLONG FileSize) +static ULONGLONG DetermineBlockTableSize_V2(TMPQHeader * pHeader, ULONGLONG MpqHeaderPos, ULONGLONG FileSize) { - ULONGLONG EndOfMpq = FileSize; - DWORD dwArchiveSize32; + ULONGLONG BlockTablePos = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); + ULONGLONG ArchiveSize = FileSize - MpqHeaderPos; - // This could only be called for MPQs version 2.0 - assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_2); - - // Check if we can rely on the archive size in the header - if((FileSize >> 0x20) == 0) + // If there is a hi-block table and it is beyond the block table, + // we can determine the block table size from it + if(pHeader->HiBlockTablePos64 != 0) { - if(pHeader->dwBlockTablePos < pHeader->dwArchiveSize) + if(pHeader->HiBlockTablePos64 > BlockTablePos) { - if((pHeader->dwArchiveSize - pHeader->dwBlockTablePos) <= (pHeader->dwBlockTableSize * sizeof(TMPQBlock))) - return pHeader->dwArchiveSize; - - // If the archive size in the header is less than real file size - dwArchiveSize32 = (DWORD)(FileSize - MpqOffset); - if(pHeader->dwArchiveSize <= dwArchiveSize32) - return pHeader->dwArchiveSize; + return (pHeader->HiBlockTablePos64 - BlockTablePos); } } - // Return the calculated archive size - return (EndOfMpq - MpqOffset); + // If we have valid archive size, we can determine the block table size from the archive size + else + { + if((BlockTablePos >> 0x20) == 0 && (ArchiveSize >> 0x20) == 0) + { + DWORD dwBlockTablePos32 = (DWORD)(BlockTablePos); + DWORD dwArchiveSize32 = (DWORD)(ArchiveSize); + + if(pHeader->dwArchiveSize == dwArchiveSize32) + { + return (dwArchiveSize32 - dwBlockTablePos32); + } + } + } + + // Default is the block table size from MPQ header + return (ULONGLONG)(pHeader->dwBlockTableSize) * sizeof(TMPQBlock); } static ULONGLONG DetermineArchiveSize_V4( @@ -381,20 +385,39 @@ static ULONGLONG DetermineArchiveSize_V4( return ArchiveSize; } +ULONGLONG GetFileOffsetMask(TMPQArchive * ha) +{ + ULONGLONG FileOffsetMask = (ULONGLONG)(-1); + + // Sanity checks + assert(ha != NULL); + assert(ha->pHeader != NULL); + + // MPQs of format 1 are 32-bit only + if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) + FileOffsetMask = (ULONGLONG)(DWORD)(-1); + return FileOffsetMask; +} + ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset) { - if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) - { - // For MPQ archive v1, any file offset is only 32-bit - return (ULONGLONG)((DWORD)ha->MpqPos + (DWORD)MpqOffset); - } - else - { - // For MPQ archive v2+, file offsets are full 64-bit - return ha->MpqPos + MpqOffset; - } + return (ha->MpqPos + MpqOffset) & ha->FileOffsetMask; } +//ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset) +//{ +// if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) +// { +// // For MPQ archive v1, any file offset is only 32-bit +// return (ULONGLONG)((DWORD)ha->MpqPos + (DWORD)MpqOffset); +// } +// else +// { +// // For MPQ archive v2+, file offsets are full 64-bit +// return ha->MpqPos + MpqOffset; +// } +//} + ULONGLONG CalculateRawSectorOffset( TMPQFile * hf, DWORD dwSectorOffset) @@ -414,9 +437,7 @@ ULONGLONG CalculateRawSectorOffset( // For MPQs version 1.0, the offset is purely 32-bit // - RawFilePos = hf->RawFilePos + dwSectorOffset; - if(hf->ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) - RawFilePos = (DWORD)hf->ha->MpqPos + (DWORD)hf->pFileEntry->ByteOffset + dwSectorOffset; + RawFilePos = (hf->RawFilePos + dwSectorOffset) & hf->ha->FileOffsetMask; // We also have to add patch header size, if patch header is present if(hf->pPatchInfo != NULL) @@ -541,34 +562,14 @@ DWORD ConvertMpqHeaderToFormat4( // We require the block table to follow hash table if(BlockTablePos64 >= HashTablePos64) { - // HashTableSize64 may be less than TblSize * sizeof(TMPQHash). - // That means that the hash table is compressed. + // Determine whether the hash table is compressed. This can be detected + // by subtracting hash table position from the block table position. pHeader->HashTableSize64 = BlockTablePos64 - HashTablePos64; - // Calculate the compressed block table size - if(pHeader->HiBlockTablePos64 != 0) - { - // BlockTableSize64 may be less than TblSize * sizeof(TMPQBlock). - // That means that the block table is compressed. - pHeader->BlockTableSize64 = pHeader->HiBlockTablePos64 - BlockTablePos64; - assert(pHeader->BlockTableSize64 <= (pHeader->dwBlockTableSize * sizeof(TMPQBlock))); - - // Determine real archive size - pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, ByteOffset, FileSize); - - // Calculate the size of the hi-block table - pHeader->HiBlockTableSize64 = pHeader->ArchiveSize64 - pHeader->HiBlockTablePos64; - assert(pHeader->HiBlockTableSize64 == (pHeader->dwBlockTableSize * sizeof(USHORT))); - } - else - { - // Determine real archive size - pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, ByteOffset, FileSize); - - // Calculate size of the block table - pHeader->BlockTableSize64 = pHeader->ArchiveSize64 - BlockTablePos64; - assert(pHeader->BlockTableSize64 <= (pHeader->dwBlockTableSize * sizeof(TMPQBlock))); - } + // Also, block table may be compressed. We check whether the HiBlockTable is there. + // If not, we try to use the archive size. Note that ArchiveSize may have + // an arbitrary value, because it is not tested by Blizzard games anymore + pHeader->BlockTableSize64 = DetermineBlockTableSize_V2(pHeader, ByteOffset, FileSize); } else { @@ -2816,17 +2817,17 @@ DWORD DefragmentFileTable(TMPQArchive * ha) { TMPQHash * pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; TMPQHash * pHash; - DWORD dwNewBlockIndex; + DWORD dwNewBlockIndex; for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++) { if(MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) - { - // If that block entry is there, set it to the hash entry - // If not, set it as DELETED - dwNewBlockIndex = DefragmentTable[MPQ_BLOCK_INDEX(pHash)]; - pHash->dwBlockIndex = (dwNewBlockIndex != HASH_ENTRY_FREE) ? dwNewBlockIndex : HASH_ENTRY_DELETED; - } + { + // If that block entry is there, set it to the hash entry + // If not, set it as DELETED + dwNewBlockIndex = DefragmentTable[MPQ_BLOCK_INDEX(pHash)]; + pHash->dwBlockIndex = (dwNewBlockIndex != HASH_ENTRY_FREE) ? dwNewBlockIndex : HASH_ENTRY_DELETED; + } } } } diff --git a/vendor/stormlib-9/src/SCompression.cpp b/vendor/stormlib-9/src/SCompression.cpp index 659c9a8..086c623 100644 --- a/vendor/stormlib-9/src/SCompression.cpp +++ b/vendor/stormlib-9/src/SCompression.cpp @@ -176,7 +176,7 @@ int Decompress_ZLIB(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, i inflateEnd(&z); } - return (nResult >= Z_OK); + return (nResult >= Z_OK); } /******************************************************************************/ @@ -279,27 +279,27 @@ static void Compress_PKLIB(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBu static int Decompress_PKLIB(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer) { TDataInfo Info; // Data information - char * work_buf; - int nResult = 0; + char * work_buf; + int nResult = 0; // Allocate Pklib's work buffer if((work_buf = STORM_ALLOC(char, EXP_BUFFER_SIZE)) != NULL) - { - // Fill data information structure - memset(work_buf, 0, EXP_BUFFER_SIZE); - Info.pbInBuff = (unsigned char *)pvInBuffer; - Info.pbInBuffEnd = (unsigned char *)pvInBuffer + cbInBuffer; - Info.pbOutBuff = (unsigned char *)pvOutBuffer; - Info.pbOutBuffEnd = (unsigned char *)pvOutBuffer + *pcbOutBuffer; - - // Do the decompression - if(explode(ReadInputData, WriteOutputData, work_buf, &Info) == CMP_NO_ERROR) - nResult = 1; - - // Give away the number of decompressed bytes - *pcbOutBuffer = (int)(Info.pbOutBuff - (unsigned char *)pvOutBuffer); - STORM_FREE(work_buf); - } + { + // Fill data information structure + memset(work_buf, 0, EXP_BUFFER_SIZE); + Info.pbInBuff = (unsigned char *)pvInBuffer; + Info.pbInBuffEnd = (unsigned char *)pvInBuffer + cbInBuffer; + Info.pbOutBuff = (unsigned char *)pvOutBuffer; + Info.pbOutBuffEnd = (unsigned char *)pvOutBuffer + *pcbOutBuffer; + + // Do the decompression + if(explode(ReadInputData, WriteOutputData, work_buf, &Info) == CMP_NO_ERROR) + nResult = 1; + + // Give away the number of decompressed bytes + *pcbOutBuffer = (int)(Info.pbOutBuff - (unsigned char *)pvOutBuffer); + STORM_FREE(work_buf); + } return nResult; } @@ -374,7 +374,7 @@ static int Decompress_BZIP2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInB BZ2_bzDecompressEnd(&strm); } - return (nResult >= BZ_OK); + return (nResult >= BZ_OK); } /******************************************************************************/ @@ -895,6 +895,16 @@ int WINAPI SCompCompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuff /* */ /*****************************************************************************/ +// Decompression table specific for Starcraft I BETA +// WAVE files are compressed by different ADPCM compression +static TDecompressTable dcmp_table_sc_beta[] = +{ + {MPQ_COMPRESSION_PKWARE, Decompress_PKLIB}, // Decompression with Pkware Data Compression Library + {MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression + {0x10, Decompress_ADPCM1_sc1b}, // IMA ADPCM mono decompression + {0x20, Decompress_ADPCM2_sc1b}, // IMA ADPCM stereo decompression +}; + // This table contains decompress functions which can be applied to // uncompressed data. The compression mask is stored in the first byte // of compressed data @@ -909,25 +919,22 @@ static TDecompressTable dcmp_table[] = {MPQ_COMPRESSION_SPARSE, Decompress_SPARSE} // Sparse decompression }; -// Decompression table specific for Starcraft I BETA -// WAVE files are compressed by different ADPCM compression -static TDecompressTable dcmp_table_sc1b[] = -{ - {MPQ_COMPRESSION_PKWARE, Decompress_PKLIB}, // Decompression with Pkware Data Compression Library - {MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression - {0x10, Decompress_ADPCM1_sc1b}, // IMA ADPCM mono decompression - {0x20, Decompress_ADPCM2_sc1b}, // IMA ADPCM stereo decompression -}; - -static int SCompDecompressInternal(TDecompressTable * table, size_t table_length, void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer) +static int SCompDecompressInternal( + TDecompressTable * table, + size_t table_length, + void * pvOutBuffer, + int * pcbOutBuffer, + void * pvInBuffer, + int cbInBuffer, + unsigned uValidMask = 0xFF) { unsigned char * pbWorkBuffer = NULL; unsigned char * pbOutBuffer = (unsigned char *)pvOutBuffer; unsigned char * pbInBuffer = (unsigned char *)pvInBuffer; unsigned char * pbOutput = (unsigned char *)pvOutBuffer; unsigned char * pbInput; - unsigned uCompressionMask; // Decompressions applied to the data - unsigned uCompressionCopy; // Decompressions applied to the data + unsigned uCompressionMask1; // Decompressions applied to the data + unsigned uCompressionMask2; // Decompressions applied to the data int cbOutBuffer = *pcbOutBuffer; // Current size of the output buffer int cbInLength; // Current size of the input buffer int nCompressCount = 0; // Number of compressions to be applied @@ -948,7 +955,8 @@ static int SCompDecompressInternal(TDecompressTable * table, size_t table_length } // Get applied compression types and decrement data length - uCompressionMask = uCompressionCopy = (unsigned char)(*pbInBuffer++); + uCompressionMask1 = ((unsigned char)(*pbInBuffer++) & (uValidMask)); + uCompressionMask2 = uCompressionMask1; cbInBuffer--; // Get current compressed data and length of it @@ -956,21 +964,21 @@ static int SCompDecompressInternal(TDecompressTable * table, size_t table_length cbInLength = cbInBuffer; // This compression function doesn't support LZMA - assert(uCompressionMask != MPQ_COMPRESSION_LZMA); + assert(uCompressionMask1 != MPQ_COMPRESSION_LZMA); // Parse the compression mask for(size_t i = 0; i < table_length; i++) { // If the mask agrees, insert the compression function to the array - if(uCompressionMask & table[i].uMask) + if(uCompressionMask1 & table[i].uMask) { - uCompressionCopy &= ~table[i].uMask; + uCompressionMask2 &= ~table[i].uMask; nCompressCount++; } } // If at least one of the compressions remaing unknown, return an error - if(nCompressCount == 0 || uCompressionCopy != 0) + if(nCompressCount == 0 || uCompressionMask2 != 0) { SetLastError(ERROR_NOT_SUPPORTED); return 0; @@ -994,7 +1002,7 @@ static int SCompDecompressInternal(TDecompressTable * table, size_t table_length for(size_t i = 0; i < table_length; i++) { // Perform the (next) decompression - if(uCompressionMask & table[i].uMask) + if(uCompressionMask1 & table[i].uMask) { // Get the correct output buffer pbOutput = (nCompressIndex & 1) ? pbWorkBuffer : pbOutBuffer; @@ -1030,11 +1038,6 @@ int WINAPI SCompDecompress(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBu return SCompDecompressInternal(dcmp_table, _countof(dcmp_table), pvOutBuffer, pcbOutBuffer, pvInBuffer, cbInBuffer); } -int WINAPI SCompDecompress_SC1B(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer) -{ - return SCompDecompressInternal(dcmp_table_sc1b, _countof(dcmp_table_sc1b), pvOutBuffer, pcbOutBuffer, pvInBuffer, cbInBuffer); -} - int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer) { DECOMPRESS pfnDecompress1 = NULL; @@ -1149,6 +1152,24 @@ int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInB return nResult; } +int WINAPI SCompDecompressX(TMPQArchive * ha, void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer) +{ + // MPQs version 2 use their own fixed list of compression flags. + if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2) + { + return SCompDecompress2(pvOutBuffer, pcbOutBuffer, pvInBuffer, cbInBuffer); + } + + // Starcraft BETA has specific decompression table. + if(ha->dwFlags & MPQ_FLAG_STARCRAFT_BETA) + { + return SCompDecompressInternal(dcmp_table_sc_beta, _countof(dcmp_table_sc_beta), pvOutBuffer, pcbOutBuffer, pvInBuffer, cbInBuffer); + } + + // Default: Use the common MPQ v1 decompression routine + return SCompDecompressInternal(dcmp_table, _countof(dcmp_table), pvOutBuffer, pcbOutBuffer, pvInBuffer, cbInBuffer); +} + /*****************************************************************************/ /* */ /* File decompression for MPK archives */ diff --git a/vendor/stormlib-9/src/SFileAddFile.cpp b/vendor/stormlib-9/src/SFileAddFile.cpp index a05de55..693f541 100644 --- a/vendor/stormlib-9/src/SFileAddFile.cpp +++ b/vendor/stormlib-9/src/SFileAddFile.cpp @@ -246,6 +246,14 @@ static DWORD WriteDataToMpqFile( BSWAP_ARRAY32_UNSIGNED(pbToWrite, dwBytesInSector); } + // Do not allow Warcraft III maps to go over 2GB. + // https://github.com/ladislav-zezula/StormLib/issues/306 + if((ha->dwFlags & MPQ_FLAG_WAR3_MAP) && (ByteOffset + dwBytesInSector) > 0x7FFFFFFF) + { + dwErrCode = ERROR_DISK_FULL; + break; + } + // Write the file sector if(!FileStream_Write(ha->pStream, &ByteOffset, pbToWrite, dwBytesInSector)) { @@ -425,7 +433,7 @@ DWORD SFileAddFile_Init( // Fix Key is not allowed if the file is not encrypted if(!(dwFlags & MPQ_FILE_ENCRYPTED)) - dwFlags &= ~MPQ_FILE_FIX_KEY; + dwFlags &= ~MPQ_FILE_KEY_V2; // If the MPQ is of version 3.0 or higher, we ignore file locale. // This is because HET and BET tables have no known support for it @@ -1295,7 +1303,7 @@ bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale) } // We have to check if the file+locale is not already there - pFileEntry = GetFileEntryLocale(ha, hf->pFileEntry->szFileName, lcNewLocale, NULL); + pFileEntry = GetFileEntryExact(ha, hf->pFileEntry->szFileName, lcNewLocale, NULL); if(pFileEntry != NULL) { SetLastError(ERROR_ALREADY_EXISTS); diff --git a/vendor/stormlib-9/src/SFileAttributes.cpp b/vendor/stormlib-9/src/SFileAttributes.cpp index eb9c9ce..251624d 100644 --- a/vendor/stormlib-9/src/SFileAttributes.cpp +++ b/vendor/stormlib-9/src/SFileAttributes.cpp @@ -391,7 +391,10 @@ DWORD SAttrLoadAttributes(TMPQArchive * ha) pbAttrFile[cbAttrFile] = 0; // Load the entire file to memory - SFileReadFile(hFile, pbAttrFile, cbAttrFile, &dwBytesRead, NULL); + if(!SFileReadFile(hFile, pbAttrFile, cbAttrFile, &dwBytesRead, NULL)) + ha->dwFlags |= (GetLastError() == ERROR_FILE_CORRUPT) ? MPQ_FLAG_MALFORMED : 0; + + // Parse the (attributes) if(dwBytesRead == cbAttrFile) dwErrCode = LoadAttributesFile(ha, pbAttrFile, cbAttrFile); diff --git a/vendor/stormlib-9/src/SFileCompactArchive.cpp b/vendor/stormlib-9/src/SFileCompactArchive.cpp index e6f96a8..b91d4e9 100644 --- a/vendor/stormlib-9/src/SFileCompactArchive.cpp +++ b/vendor/stormlib-9/src/SFileCompactArchive.cpp @@ -163,7 +163,7 @@ static DWORD CopyMpqFileSectors( if(dwErrCode == ERROR_SUCCESS && (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)) { dwFileKey2 = dwFileKey1 = hf->dwFileKey; - if(pFileEntry->dwFlags & MPQ_FILE_FIX_KEY) + if(pFileEntry->dwFlags & MPQ_FILE_KEY_V2) { dwFileKey2 = (dwFileKey1 ^ pFileEntry->dwFileSize) - (DWORD)pFileEntry->ByteOffset; dwFileKey2 = (dwFileKey2 + (DWORD)MpqFilePos) ^ pFileEntry->dwFileSize; diff --git a/vendor/stormlib-9/src/SFileCreateArchive.cpp b/vendor/stormlib-9/src/SFileCreateArchive.cpp index c0ea367..bae3dcc 100644 --- a/vendor/stormlib-9/src/SFileCreateArchive.cpp +++ b/vendor/stormlib-9/src/SFileCreateArchive.cpp @@ -238,6 +238,9 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea pHeader->dwBlockTablePos = pHeader->dwHashTablePos + dwHashTableSize * sizeof(TMPQHash); pHeader->dwBlockTableSize = dwBlockTableSize; + // Set the mask for MPQ byte offset + ha->FileOffsetMask = GetFileOffsetMask(ha); + // For MPQs version 4 and higher, we set the size of raw data block // for calculating MD5 if(pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_4) diff --git a/vendor/stormlib-9/src/SFileGetFileInfo.cpp b/vendor/stormlib-9/src/SFileGetFileInfo.cpp index 4e004da..440fc08 100644 --- a/vendor/stormlib-9/src/SFileGetFileInfo.cpp +++ b/vendor/stormlib-9/src/SFileGetFileInfo.cpp @@ -68,6 +68,10 @@ static bool GetInfo_BufferCheck(void * pvFileInfo, DWORD cbFileInfo, DWORD cbDat static bool GetInfo(void * pvFileInfo, DWORD cbFileInfo, const void * pvData, DWORD cbData, LPDWORD pcbLengthNeeded) { + // Verify the input parameter + if(pvData == NULL) + return GetInfo_ReturnError(ERROR_INVALID_PARAMETER); + // Verify buffer pointer and buffer size if(!GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded)) return false; @@ -81,6 +85,10 @@ static bool GetInfo_Allocated(void * pvFileInfo, DWORD cbFileInfo, void * pvData { bool bResult; + // Verify the input parameter + if(pvData == NULL) + return GetInfo_ReturnError(ERROR_INVALID_PARAMETER); + // Verify buffer pointer and buffer size if((bResult = GetInfo_BufferCheck(pvFileInfo, cbFileInfo, cbData, pcbLengthNeeded)) != false) memcpy(pvFileInfo, pvData, cbData); @@ -401,15 +409,21 @@ bool WINAPI SFileGetFileInfo( return GetInfo(pvFileInfo, cbFileInfo, &hf->dwHashIndex, sizeof(DWORD), pcbLengthNeeded); case SFileInfoNameHash1: + if(hf->pHashEntry == NULL) + return GetInfo_ReturnError(ERROR_INVALID_PARAMETER); return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName1, sizeof(DWORD), pcbLengthNeeded); case SFileInfoNameHash2: + if(hf->pHashEntry == NULL) + return GetInfo_ReturnError(ERROR_INVALID_PARAMETER); return GetInfo(pvFileInfo, cbFileInfo, &hf->pHashEntry->dwName2, sizeof(DWORD), pcbLengthNeeded); case SFileInfoNameHash3: return GetInfo(pvFileInfo, cbFileInfo, &pFileEntry->FileNameHash, sizeof(ULONGLONG), pcbLengthNeeded); case SFileInfoLocale: + if(hf->pHashEntry == NULL) + return GetInfo_ReturnError(ERROR_INVALID_PARAMETER); dwInt32Value = SFILE_MAKE_LCID(hf->pHashEntry->Locale, hf->pHashEntry->Platform); return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); @@ -437,7 +451,7 @@ bool WINAPI SFileGetFileInfo( case SFileInfoEncryptionKeyRaw: dwInt32Value = hf->dwFileKey; - if(pFileEntry->dwFlags & MPQ_FILE_FIX_KEY) + if(pFileEntry->dwFlags & MPQ_FILE_KEY_V2) dwInt32Value = (dwInt32Value ^ pFileEntry->dwFileSize) - (DWORD)hf->MpqFilePos; return GetInfo(pvFileInfo, cbFileInfo, &dwInt32Value, sizeof(DWORD), pcbLengthNeeded); @@ -564,11 +578,11 @@ static DWORD CreatePseudoFileName(HANDLE hFile, TFileEntry * pFileEntry, char * bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName) { - TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle + TMPQFile * hf; DWORD dwErrCode = ERROR_INVALID_HANDLE; // Check valid parameters - if(IsValidFileHandle(hFile)) + if((hf = IsValidFileHandle(hFile)) != NULL) { TFileEntry * pFileEntry = hf->pFileEntry; diff --git a/vendor/stormlib-9/src/SFileListFile.cpp b/vendor/stormlib-9/src/SFileListFile.cpp index de34d5b..3b631ac 100644 --- a/vendor/stormlib-9/src/SFileListFile.cpp +++ b/vendor/stormlib-9/src/SFileListFile.cpp @@ -558,6 +558,27 @@ static DWORD SFileAddArbitraryListFile( return (pCache != NULL) ? ERROR_SUCCESS : ERROR_FILE_CORRUPT; } +static DWORD SFileAddArbitraryListFile( + TMPQArchive * ha, + const char ** listFileEntries, + DWORD dwEntryCount) +{ + if(listFileEntries != NULL && dwEntryCount > 0) + { + // Get the next line + for(DWORD dwListFileNum = 0; dwListFileNum < dwEntryCount; dwListFileNum++) + { + const char * listFileEntry = listFileEntries[dwListFileNum]; + if(listFileEntry != NULL) + { + SListFileCreateNodeForAllLocales(ha, listFileEntry); + } + } + } + + return (listFileEntries != NULL && dwEntryCount > 0) ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER; +} + static DWORD SFileAddInternalListFile( TMPQArchive * ha, HANDLE hMpq) @@ -662,6 +683,32 @@ DWORD WINAPI SFileAddListFile(HANDLE hMpq, const TCHAR * szListFile) return dwErrCode; } +DWORD WINAPI SFileAddListFileEntries(HANDLE hMpq, const char ** listFileEntries, DWORD dwEntryCount) +{ + TMPQArchive * ha = (TMPQArchive *)hMpq; + DWORD dwErrCode = ERROR_SUCCESS; + + // Add the listfile for each MPQ in the patch chain + while(ha != NULL) + { + if(listFileEntries != NULL && dwEntryCount > 0) + dwErrCode = SFileAddArbitraryListFile(ha, listFileEntries, dwEntryCount); + else + dwErrCode = SFileAddInternalListFile(ha, hMpq); + + // Also, add three special files to the listfile: + // (listfile) itself, (attributes) and (signature) + SListFileCreateNodeForAllLocales(ha, LISTFILE_NAME); + SListFileCreateNodeForAllLocales(ha, SIGNATURE_NAME); + SListFileCreateNodeForAllLocales(ha, ATTRIBUTES_NAME); + + // Move to the next archive in the chain + ha = ha->haPatch; + } + + return dwErrCode; +} + //----------------------------------------------------------------------------- // Enumerating files in listfile diff --git a/vendor/stormlib-9/src/SFileOpenArchive.cpp b/vendor/stormlib-9/src/SFileOpenArchive.cpp index 16e2491..4b2d3b4 100644 --- a/vendor/stormlib-9/src/SFileOpenArchive.cpp +++ b/vendor/stormlib-9/src/SFileOpenArchive.cpp @@ -387,7 +387,7 @@ bool WINAPI SFileOpenArchive( } // Check for MPK archives (Longwu Online - MPQ fork) - if(MapType == MapTypeNotRecognized && dwHeaderID == ID_MPK) + if(MapType == MapTypeNotRecognized && (dwFlags & MPQ_OPEN_FORCE_MPQ_V1) == 0 && dwHeaderID == ID_MPK) { // Now convert the MPK header to MPQ Header version 4 dwErrCode = ConvertMpkHeaderToFormat4(ha, FileSize, dwFlags); @@ -463,16 +463,24 @@ bool WINAPI SFileOpenArchive( if(IsStarcraftBetaArchive(ha->pHeader)) ha->dwFlags |= MPQ_FLAG_STARCRAFT_BETA; - // Remember whether whis is a map for Warcraft III - if(MapType == MapTypeWarcraft3) - { - ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_W3X; - ha->dwFlags |= MPQ_FLAG_WAR3_MAP; - } + // Set the mask for the file offset. In MPQs version 1, + // all offsets are 32-bit and overflow is allowed. + // For MPQs v2+, file offset if 64-bit. + ha->FileOffsetMask = GetFileOffsetMask(ha); - // If this is starcraft map, set the flag mask - if(MapType == MapTypeStarcraft) - ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_SCX; + // Maps from StarCraft and Warcraft III need special treatment + switch(MapType) + { + case MapTypeStarcraft: + ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_SCX; + ha->dwFlags |= MPQ_FLAG_STARCRAFT; + break; + + case MapTypeWarcraft3: + ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS_W3X; + ha->dwFlags |= MPQ_FLAG_WAR3_MAP; + break; + } // Set the size of file sector ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize); diff --git a/vendor/stormlib-9/src/SFileOpenFileEx.cpp b/vendor/stormlib-9/src/SFileOpenFileEx.cpp index a14ffee..157ad15 100644 --- a/vendor/stormlib-9/src/SFileOpenFileEx.cpp +++ b/vendor/stormlib-9/src/SFileOpenFileEx.cpp @@ -16,11 +16,13 @@ /* Local functions */ /*****************************************************************************/ +// Finds hash index of the entry that was open by pseudo-name static DWORD FindHashIndex(TMPQArchive * ha, DWORD dwFileIndex) { TMPQHash * pHashTableEnd; TMPQHash * pHash; - DWORD dwFirstIndex = HASH_ENTRY_FREE; + DWORD dwHashIndex = HASH_ENTRY_FREE; + DWORD dwCount = 0; // Should only be called if the archive has hash table assert(ha->pHashTable != NULL); @@ -32,15 +34,18 @@ static DWORD FindHashIndex(TMPQArchive * ha, DWORD dwFileIndex) { if(MPQ_BLOCK_INDEX(pHash) == dwFileIndex) { - // Duplicate hash entry found - if(dwFirstIndex != HASH_ENTRY_FREE) + // Example: MPQ_2023_v1_Lusin2Rpg1.28.w3x, file index 24483 + // ReplaceableTextures\CommandButtons\BTNHaboss79.blp + // Hash Table Index #1 = 18 + // Hash Table Index #2 = 8446 + if(dwCount++ > 0) return HASH_ENTRY_FREE; - dwFirstIndex = (DWORD)(pHash - ha->pHashTable); + dwHashIndex = (DWORD)(pHash - ha->pHashTable); } } - // Return the hash table entry index - return dwFirstIndex; + // Return the found hash index, if there are no duplicities + return dwHashIndex; } static const char * GetPatchFileName(TMPQArchive * ha, const char * szFileName, char * szBuffer) @@ -298,32 +303,32 @@ bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearch if(dwErrCode == ERROR_SUCCESS) { // If we didn't find the file, try to open it using pseudo file name ("File - if (pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0) + if(pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0) { // Check the pseudo-file name ("File00000001.ext") - if ((bOpenByIndex = IsPseudoFileName(szFileName, &dwFileIndex)) == true) + if((bOpenByIndex = IsPseudoFileName(szFileName, &dwFileIndex)) == true) { // Get the file entry for the file - if (dwFileIndex < ha->dwFileTableSize) + if(dwFileIndex < ha->dwFileTableSize) { pFileEntry = ha->pFileTable + dwFileIndex; } } // Still not found? - if (pFileEntry == NULL) + if(pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0) { dwErrCode = ERROR_FILE_NOT_FOUND; } } // Perform some checks of invalid files - if (pFileEntry != NULL) + if(pFileEntry != NULL) { // MPQ protectors use insanely amount of fake files, often with very high size. // We won't open any files whose compressed size is bigger than archive size // If the file is not compressed, its size cannot be bigger than archive size - if ((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize)) + if((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize)) { dwErrCode = ERROR_FILE_CORRUPT; pFileEntry = NULL; diff --git a/vendor/stormlib-9/src/SFileReadFile.cpp b/vendor/stormlib-9/src/SFileReadFile.cpp index 39f794e..b0698c1 100644 --- a/vendor/stormlib-9/src/SFileReadFile.cpp +++ b/vendor/stormlib-9/src/SFileReadFile.cpp @@ -13,6 +13,11 @@ #include "StormLib.h" #include "StormCommon.h" +//----------------------------------------------------------------------------- +// External references (not public functions) + +int WINAPI SCompDecompressX(TMPQArchive * ha, void * pvOutBuffer, int * pcbOutBuffer, void * pbInBuffer, int cbInBuffer); + //----------------------------------------------------------------------------- // Local functions @@ -171,18 +176,10 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, // Remember the last used compression hf->dwCompression0 = pbInSector[0]; - // Decompress the data - if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2) - { - nResult = SCompDecompress2(pbOutSector, &cbOutSector, pbInSector, cbInSector); - } - else - { - if(ha->dwFlags & MPQ_FLAG_STARCRAFT_BETA) - nResult = SCompDecompress_SC1B(pbOutSector, &cbOutSector, pbInSector, cbInSector); - else - nResult = SCompDecompress(pbOutSector, &cbOutSector, pbInSector, cbInSector); - } + // Decompress the data. We need to perform MPQ-specific decompression, + // as multiple Blizzard games may have their own decompression tables + // and even decompression methods. + nResult = SCompDecompressX(ha, pbOutSector, &cbOutSector, pbInSector, cbInSector); } // Is the file compressed by PKWARE Data Compression Library ? diff --git a/vendor/stormlib-9/src/SFileVerify.cpp b/vendor/stormlib-9/src/SFileVerify.cpp index 33cd747..908cac9 100644 --- a/vendor/stormlib-9/src/SFileVerify.cpp +++ b/vendor/stormlib-9/src/SFileVerify.cpp @@ -863,7 +863,7 @@ DWORD SSignFileFinish(TMPQArchive * ha) // Sign the hash memset(WeakSignature, 0, sizeof(WeakSignature)); rsa_sign_hash_ex(Md5Digest, sizeof(Md5Digest), WeakSignature + 8, &signature_len, LTC_LTC_PKCS_1_V1_5, 0, 0, hash_idx, 0, &key); - memrev(WeakSignature + 8, MPQ_WEAK_SIGNATURE_SIZE); + memrev(WeakSignature + 8, MPQ_WEAK_SIGNATURE_SIZE); rsa_free(&key); // Write the signature to the MPQ. Don't use SFile* functions, but write the hash directly diff --git a/vendor/stormlib-9/src/StormCommon.h b/vendor/stormlib-9/src/StormCommon.h index ceab22f..4440500 100644 --- a/vendor/stormlib-9/src/StormCommon.h +++ b/vendor/stormlib-9/src/StormCommon.h @@ -82,7 +82,7 @@ #endif //----------------------------------------------------------------------------- -// MTYPE definition - specifies what kind of MPQ is the map type +// MTYPE definition - specifies what kind of MPQ is the file typedef enum _MTYPE { @@ -251,6 +251,7 @@ TMPQFile * IsValidFileHandle(HANDLE hFile); //----------------------------------------------------------------------------- // Support for MPQ file tables +ULONGLONG GetFileOffsetMask(TMPQArchive * ha); ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset); ULONGLONG CalculateRawSectorOffset(TMPQFile * hf, DWORD dwSectorOffset); diff --git a/vendor/stormlib-9/src/StormLib.h b/vendor/stormlib-9/src/StormLib.h index e45f99d..e211cd8 100644 --- a/vendor/stormlib-9/src/StormLib.h +++ b/vendor/stormlib-9/src/StormLib.h @@ -143,8 +143,8 @@ extern "C" { //----------------------------------------------------------------------------- // Defines -#define STORMLIB_VERSION 0x0918 // Current version of StormLib (9.24) -#define STORMLIB_VERSION_STRING "9.24" // String version of StormLib version +#define STORMLIB_VERSION 0x0919 // Current version of StormLib +#define STORMLIB_VERSION_STRING "9.25" // Current version of StormLib as string #define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') #define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B') @@ -194,15 +194,16 @@ extern "C" { #define MPQ_FLAG_CHECK_SECTOR_CRC 0x00000020 // Checking sector CRC when reading files #define MPQ_FLAG_SAVING_TABLES 0x00000040 // If set, we are saving MPQ internal files and MPQ tables #define MPQ_FLAG_PATCH 0x00000080 // If set, this MPQ is a patch archive -#define MPQ_FLAG_WAR3_MAP 0x00000100 // If set, this MPQ is a Warcraft III map -#define MPQ_FLAG_STARCRAFT_BETA 0x00000200 // If set, this MPQ is StarDat.mpq from Starcraft I BETA -#define MPQ_FLAG_LISTFILE_NONE 0x00000400 // Set when no (listfile) was found in InvalidateInternalFiles -#define MPQ_FLAG_LISTFILE_NEW 0x00000800 // Set when (listfile) invalidated by InvalidateInternalFiles -#define MPQ_FLAG_LISTFILE_FORCE 0x00001000 // Save updated listfile on exit -#define MPQ_FLAG_ATTRIBUTES_NONE 0x00002000 // Set when no (attributes) was found in InvalidateInternalFiles -#define MPQ_FLAG_ATTRIBUTES_NEW 0x00004000 // Set when (attributes) invalidated by InvalidateInternalFiles -#define MPQ_FLAG_SIGNATURE_NONE 0x00008000 // Set when no (signature) was found in InvalidateInternalFiles -#define MPQ_FLAG_SIGNATURE_NEW 0x00010000 // Set when (signature) invalidated by InvalidateInternalFiles +#define MPQ_FLAG_STARCRAFT_BETA 0x00000100 // If set, this MPQ is from Starcraft I BETA +#define MPQ_FLAG_STARCRAFT 0x00000200 // If set, this MPQ is from Starcraft I +#define MPQ_FLAG_WAR3_MAP 0x00000400 // If set, this MPQ is a Warcraft III map +#define MPQ_FLAG_LISTFILE_NONE 0x00000800 // Set when no (listfile) was found in InvalidateInternalFiles +#define MPQ_FLAG_LISTFILE_NEW 0x00001000 // Set when (listfile) invalidated by InvalidateInternalFiles +#define MPQ_FLAG_LISTFILE_FORCE 0x00002000 // Save updated listfile on exit +#define MPQ_FLAG_ATTRIBUTES_NONE 0x00004000 // Set when no (attributes) was found in InvalidateInternalFiles +#define MPQ_FLAG_ATTRIBUTES_NEW 0x00008000 // Set when (attributes) invalidated by InvalidateInternalFiles +#define MPQ_FLAG_SIGNATURE_NONE 0x00010000 // Set when no (signature) was found in InvalidateInternalFiles +#define MPQ_FLAG_SIGNATURE_NEW 0x00020000 // Set when (signature) invalidated by InvalidateInternalFiles // Values for TMPQArchive::dwSubType #define MPQ_SUBTYPE_MPQ 0x00000000 // The file is a MPQ file (Blizzard games) @@ -214,11 +215,11 @@ extern "C" { #define SFILE_INVALID_POS 0xFFFFFFFF #define SFILE_INVALID_ATTRIBUTES 0xFFFFFFFF -// Flags for SFileAddFile +// Flags for TMPQBlock::dwFlags #define MPQ_FILE_IMPLODE 0x00000100 // Implode method (By PKWARE Data Compression Library) #define MPQ_FILE_COMPRESS 0x00000200 // Compress methods (By multiple methods) -#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted -#define MPQ_FILE_FIX_KEY 0x00020000 // File decryption key has to be fixed +#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates an encrypted file +#define MPQ_FILE_KEY_V2 0x00020000 // Indicates an encrypted file with key v2 #define MPQ_FILE_PATCH_FILE 0x00100000 // The file is a patch file. Raw file data begin with TPatchInfo structure #define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam) #define MPQ_FILE_DELETE_MARKER 0x02000000 // File is a deletion marker. Used in MPQ patches, indicating that the file no longer exists. @@ -232,10 +233,12 @@ extern "C" { #define MPQ_FILE_DEFAULT_INTERNAL 0xFFFFFFFF // Use default flags for internal files +#define MPQ_FILE_FIX_KEY 0x00020000 // Obsolete, do not use + #define MPQ_FILE_VALID_FLAGS (MPQ_FILE_IMPLODE | \ MPQ_FILE_COMPRESS | \ MPQ_FILE_ENCRYPTED | \ - MPQ_FILE_FIX_KEY | \ + MPQ_FILE_KEY_V2 | \ MPQ_FILE_PATCH_FILE | \ MPQ_FILE_SINGLE_UNIT | \ MPQ_FILE_DELETE_MARKER | \ @@ -246,7 +249,7 @@ extern "C" { #define MPQ_FILE_VALID_FLAGS_W3X (MPQ_FILE_IMPLODE | \ MPQ_FILE_COMPRESS | \ MPQ_FILE_ENCRYPTED | \ - MPQ_FILE_FIX_KEY | \ + MPQ_FILE_KEY_V2 | \ MPQ_FILE_DELETE_MARKER | \ MPQ_FILE_SECTOR_CRC | \ MPQ_FILE_SIGNATURE | \ @@ -255,9 +258,12 @@ extern "C" { #define MPQ_FILE_VALID_FLAGS_SCX (MPQ_FILE_IMPLODE | \ MPQ_FILE_COMPRESS | \ MPQ_FILE_ENCRYPTED | \ - MPQ_FILE_FIX_KEY | \ + MPQ_FILE_KEY_V2 | \ MPQ_FILE_EXISTS) +// Flags for TPatchInfo::dwFlags +#define MPQ_PATCH_INFO_VALID 0x80000000 // Set if the patch info is valid + // We need to mask out the upper 4 bits of the block table index. // This is because it gets shifted out when calculating block table offset // BlockTableOffset = pHash->dwBlockIndex << 0x04 @@ -471,6 +477,8 @@ typedef enum _SFileInfoClass SFileInfoEncryptionKey, // File encryption key SFileInfoEncryptionKeyRaw, // Unfixed value of the file key SFileInfoCRC32, // CRC32 of the file + + SFileInfoInvalid = 0xFFF, // Invalid file info class } SFileInfoClass; //----------------------------------------------------------------------------- @@ -675,7 +683,7 @@ typedef struct _TMPQBlock typedef struct _TPatchInfo { DWORD dwLength; // Length of patch info header, in bytes - DWORD dwFlags; // Flags. 0x80000000 = MD5 (?) + DWORD dwFlags; // Flags. 0x80000000 = valid (?) DWORD dwDataSize; // Uncompressed size of the patch file BYTE md5[0x10]; // MD5 of the entire patch file after decompression @@ -822,6 +830,7 @@ typedef struct _TMPQArchive ULONGLONG UserDataPos; // Position of user data (relative to the begin of the file) ULONGLONG MpqPos; // MPQ header offset (relative to the begin of the file) ULONGLONG FileSize; // Size of the file at the moment of file open + ULONGLONG FileOffsetMask; // 0xFFFFFFFF for MPQ v 1, otherwise 0xFFFFFFFFFFFFFFFFull struct _TMPQArchive * haPatch; // Pointer to patch archive, if any struct _TMPQArchive * haBase; // Pointer to base ("previous version") archive, if any @@ -1025,6 +1034,7 @@ bool WINAPI SFileCloseArchive(HANDLE hMpq); // so you can use this API to combining more listfiles. // Note that this function is internally called by SFileFindFirstFile DWORD WINAPI SFileAddListFile(HANDLE hMpq, const TCHAR * szListFile); +DWORD WINAPI SFileAddListFileEntries(HANDLE hMpq, const char ** listFileEntries, DWORD dwEntryCount); // Archive compacting bool WINAPI SFileSetCompactCallback(HANDLE hMpq, SFILE_COMPACT_CALLBACK CompactCB, void * pvUserData); @@ -1120,7 +1130,6 @@ int WINAPI SCompExplode (void * pvOutBuffer, int * pcbOutBuffer, void * pv int WINAPI SCompCompress (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer, unsigned uCompressionMask, int nCmpType, int nCmpLevel); int WINAPI SCompDecompress (void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer); int WINAPI SCompDecompress2(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer); -int WINAPI SCompDecompress_SC1B(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer); //----------------------------------------------------------------------------- // Non-Windows support for SetLastError/GetLastError diff --git a/vendor/stormlib-9/src/StormPort.h b/vendor/stormlib-9/src/StormPort.h index aa2c9f5..48a5e1f 100644 --- a/vendor/stormlib-9/src/StormPort.h +++ b/vendor/stormlib-9/src/StormPort.h @@ -20,7 +20,7 @@ /* 12.11.03 1.02 Dan Macintosh compatibility */ /* 24.07.04 1.03 Sam Mac OS X compatibility */ /* 22.11.06 1.04 Sam Mac OS X compatibility (for StormLib 6.0) */ -/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */ +/* 31.12.06 1.05 XPinguin Full GNU/Linux compatibility */ /* 17.10.12 1.05 Lad Moved error codes so they don't overlap with errno.h */ /*****************************************************************************/ diff --git a/vendor/stormlib-9/src/huffman/huff.cpp b/vendor/stormlib-9/src/huffman/huff.cpp index 6930354..1b81017 100644 --- a/vendor/stormlib-9/src/huffman/huff.cpp +++ b/vendor/stormlib-9/src/huffman/huff.cpp @@ -269,24 +269,6 @@ TInputStream::TInputStream(void * pvInBuffer, size_t cbInBuffer) BitCount = 0; } -// Gets 7 bits from the stream. DOES NOT remove the bits from input stream -unsigned int TInputStream::Peek7Bits() -{ - unsigned int dwReloadByte = 0; - - // If there is not enough bits to get the value, - // we have to add 8 more bits from the input buffer - if(BitCount < 7) - { - dwReloadByte = *pbInBuffer++; - BitBuffer |= dwReloadByte << BitCount; - BitCount += 8; - } - - // Return the first available 7 bits. DO NOT remove them from the input stream - return (BitBuffer & 0x7F); -} - // Gets one bit from input stream unsigned int TInputStream::Get1Bit() { @@ -330,6 +312,30 @@ unsigned int TInputStream::Get8Bits() return dwOneByte; } +// Gets 7 bits from the stream. DOES NOT remove the bits from input stream +bool TInputStream::Peek7Bits(unsigned int & Value) +{ + unsigned int Value8Bits = 0; + + // If there is not enough bits to get the value, + // we have to add 8 more bits from the input buffer + if(BitCount < 7) + { + // Load additional 8 bits. Be careful if we have no more data + if(pbInBuffer >= pbInBufferEnd) + return false; + Value8Bits = *pbInBuffer++; + + // Add these 8 bits to the bit buffer + BitBuffer |= Value8Bits << BitCount; + BitCount += 8; + } + + // Return 7 bits of data. DO NOT remove them from the input stream + Value = (BitBuffer & 0x7F); + return true; +} + void TInputStream::SkipBits(unsigned int dwBitsToSkip) { unsigned int dwReloadByte = 0; @@ -696,16 +702,13 @@ unsigned int THuffmannTree::DecodeOneByte(TInputStream * is) THTreeItem * pItem; unsigned int ItemLinkIndex; unsigned int BitCount = 0; + bool bHasItemLinkIndex; - // Check for the end of the input stream - if(is->pbInBuffer >= is->pbInBufferEnd && is->BitCount < 7) - return 0x1FF; - - // Get the eventual quick-link index - ItemLinkIndex = is->Peek7Bits(); + // Try to retrieve quick link index + bHasItemLinkIndex = is->Peek7Bits(ItemLinkIndex); // Is the quick-link item valid? - if(QuickLinks[ItemLinkIndex].ValidValue > MinValidValue) + if(bHasItemLinkIndex && QuickLinks[ItemLinkIndex].ValidValue > MinValidValue) { // If that item needs less than 7 bits, we can get decompressed value directly if(QuickLinks[ItemLinkIndex].ValidBits <= 7) @@ -745,7 +748,7 @@ unsigned int THuffmannTree::DecodeOneByte(TInputStream * is) // If we didn't get the item from the quick-link array, // set the entry in it - if(QuickLinks[ItemLinkIndex].ValidValue < MinValidValue) + if(bHasItemLinkIndex && QuickLinks[ItemLinkIndex].ValidValue < MinValidValue) { // If the current compressed byte was more than 7 bits, // set a quick-link item with pointer to tree item @@ -876,10 +879,10 @@ unsigned int THuffmannTree::Decompress(void * pvOutBuffer, unsigned int cbOutLen IncWeightsAndRebalance(ItemsByByte[DecompressedValue]); } - // A byte successfully decoded - store it in the output stream - *pbOutBuffer++ = (unsigned char)DecompressedValue; + // Store the byte to the output stream if(pbOutBuffer >= pbOutBufferEnd) break; + *pbOutBuffer++ = (unsigned char)DecompressedValue; if(bIsCmp0) { diff --git a/vendor/stormlib-9/src/huffman/huff.h b/vendor/stormlib-9/src/huffman/huff.h index b75acbb..cf1ca4c 100644 --- a/vendor/stormlib-9/src/huffman/huff.h +++ b/vendor/stormlib-9/src/huffman/huff.h @@ -29,8 +29,8 @@ class TInputStream TInputStream(void * pvInBuffer, size_t cbInBuffer); unsigned int Get1Bit(); - unsigned int Peek7Bits(); unsigned int Get8Bits(); + bool Peek7Bits(unsigned int & Value); void SkipBits(unsigned int BitCount); unsigned char * pbInBufferEnd; // End position in the the input buffer diff --git a/vendor/stormlib-9/src/libtomcrypt/src/hashes/sha256.c b/vendor/stormlib-9/src/libtomcrypt/src/hashes/sha256.c new file mode 100644 index 0000000..edd3d44 --- /dev/null +++ b/vendor/stormlib-9/src/libtomcrypt/src/hashes/sha256.c @@ -0,0 +1,340 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "../headers/tomcrypt.h" + +/** + @file sha256.c + LTC_SHA256 by Tom St Denis +*/ + +#ifdef LTC_SHA256 + +const struct ltc_hash_descriptor sha256_desc = +{ + "sha256", + 0, + 32, + 64, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, + 9, + + &sha256_init, + &sha256_process, + &sha256_done, + &sha256_test, + NULL +}; + +#ifdef LTC_SMALL_CODE +/* the K array */ +static const ulong32 K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; +#endif + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +/* compress 512-bits */ +#ifdef LTC_CLEAN_STACK +static int _sha256_compress(hash_state * md, unsigned char *buf) +#else +static int sha256_compress(hash_state * md, unsigned char *buf) +#endif +{ + ulong32 S[8], W[64], t0, t1; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha256.state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifdef LTC_SMALL_CODE +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 64; ++i) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } +#else +#define RND(a,b,c,d,e,f,g,h,i,ki) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); + +#undef RND + +#endif + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha256.state[i] = md->sha256.state[i] + S[i]; + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int sha256_compress(hash_state * md, unsigned char *buf) +{ + int err; + err = _sha256_compress(md, buf); + burn_stack(sizeof(ulong32) * 74); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha256_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha256.curlen = 0; + md->sha256.length = 0; + md->sha256.state[0] = 0x6A09E667UL; + md->sha256.state[1] = 0xBB67AE85UL; + md->sha256.state[2] = 0x3C6EF372UL; + md->sha256.state[3] = 0xA54FF53AUL; + md->sha256.state[4] = 0x510E527FUL; + md->sha256.state[5] = 0x9B05688CUL; + md->sha256.state[6] = 0x1F83D9ABUL; + md->sha256.state[7] = 0x5BE0CD19UL; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha256_process, sha256_compress, sha256, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +int sha256_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha256.curlen >= sizeof(md->sha256.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->sha256.length += md->sha256.curlen * 8; + + /* append the '1' bit */ + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha256.curlen > 56) { + while (md->sha256.curlen < 64) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + sha256_compress(md, md->sha256.buf); + md->sha256.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->sha256.curlen < 56) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha256.length, md->sha256.buf+56); + sha256_compress(md, md->sha256.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(md->sha256.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha256_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + char *msg; + unsigned char hash[32]; + } tests[] = { + { "abc", + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } + }, + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha256_init(&md); + sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); + sha256_done(&md, tmp); + if (XMEMCMP(tmp, tests[i].hash, 32) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#ifdef LTC_SHA224 +#include "sha224.c" +#endif + +#endif + + + +/* $Source: /cvs/libtom/libtomcrypt/src/hashes/sha2/sha256.c,v $ */ +/* $Revision: 1.11 $ */ +/* $Date: 2007/05/12 14:25:28 $ */ diff --git a/vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_custom.h b/vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_custom.h index 312a4c2..d53eef7 100644 --- a/vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_custom.h +++ b/vendor/stormlib-9/src/libtomcrypt/src/headers/tomcrypt_custom.h @@ -11,29 +11,29 @@ #define LTC_NO_ROLC #define LTC_SOURCE +#define LTC_SHA256 #define LTC_SHA1 #define LTC_MD5 #define LTC_DER -#define LTC_RC4 -#define USE_LTM #define LTM_DESC +#define USE_LTM /* macros for various libc functions you can change for embedded targets */ #ifndef XMALLOC - #ifdef malloc + #ifdef malloc #define LTC_NO_PROTOTYPES #endif #define XMALLOC LibTomMalloc #endif #ifndef XREALLOC - #ifdef realloc + #ifdef realloc #define LTC_NO_PROTOTYPES #endif #define XREALLOC LibTomRealloc #endif #ifndef XCALLOC - #ifdef calloc + #ifdef calloc #define LTC_NO_PROTOTYPES #endif #define XCALLOC LibTomCalloc @@ -58,7 +58,7 @@ #define XMEMCPY memcpy #endif #ifndef XMEMCMP - #ifdef memcmp + #ifdef memcmp #define LTC_NO_PROTOTYPES_MEMCMP #endif #define XMEMCMP memcmp @@ -91,19 +91,19 @@ #define LTC_BLOWFISH #define LTC_DES #define LTC_CAST5 - + #define LTC_NO_MODES #define LTC_ECB_MODE #define LTC_CBC_MODE #define LTC_CTR_MODE - + #define LTC_NO_HASHES #define LTC_SHA1 #define LTC_SHA512 #define LTC_SHA384 #define LTC_SHA256 #define LTC_SHA224 - + #define LTC_NO_MACS #define LTC_HMAC #define LTC_OMAC @@ -114,11 +114,11 @@ #define LTC_YARROW #define LTC_DEVRANDOM #define TRY_URANDOM_FIRST - + #define LTC_NO_PK #define LTC_MRSA #define LTC_MECC -#endif +#endif /* Use small code where possible */ /* #define LTC_SMALL_CODE */ @@ -194,7 +194,7 @@ #define LTC_LRW_MODE #ifndef LTC_NO_TABLES /* like GCM mode this will enable 16 8x128 tables [64KB] that make - * seeking very fast. + * seeking very fast. */ #define LRW_TABLES #endif @@ -205,7 +205,7 @@ #endif /* LTC_NO_MODES */ /* ---> One-Way Hash Functions <--- */ -#ifndef LTC_NO_HASHES +#ifndef LTC_NO_HASHES #define LTC_CHC_HASH #define LTC_WHIRLPOOL @@ -252,7 +252,7 @@ /* Use 64KiB tables */ #ifndef LTC_NO_TABLES - #define LTC_GCM_TABLES + #define LTC_GCM_TABLES #endif /* USE SSE2? requires GCC works on x86_32 and x86_64*/ @@ -319,7 +319,7 @@ #define LTC_MRSA /* Include Katja (a Rabin variant like RSA) */ -/* #define MKAT */ +/* #define MKAT */ /* Digital Signature Algorithm */ #define LTC_MDSA @@ -332,7 +332,7 @@ #if defined(TFM_LTC_DESC) && defined(LTC_MECC) #define LTC_MECC_ACCEL -#endif +#endif /* do we want fixed point ECC */ /* #define LTC_MECC_FP */ @@ -376,9 +376,9 @@ #ifdef LTC_MRSA #define LTC_PKCS_1 -#endif +#endif -#if defined(LTC_DER) && !defined(MPI) +#if defined(LTC_DER) && !defined(MPI) #error ASN.1 DER requires MPI functionality #endif