From 8d062b935680544381173789f42d0df3cd0f4ade Mon Sep 17 00:00:00 2001 From: fzxx <53783792+fzxx@users.noreply.github.com> Date: Mon, 11 May 2026 12:15:48 +0800 Subject: [PATCH] Add XChaCha20 algorithm, using a 64-bit counter to support large files. --- C/7zArcIn.c | 651 ++++----- C/7zVersion.h | 6 +- C/Compiler.h | 5 + C/DllSecur.c | 6 +- C/MtDec.c | 4 +- C/Util/7z/7zMain.c | 7 +- C/Util/7zipInstall/7zipInstall.c | 38 +- C/Util/7zipUninstall/7zipUninstall.c | 58 +- C/Util/SfxSetup/SfxSetup.c | 14 +- C/XzDec.c | 47 +- CPP/7zip/7zip.mak | 2 +- CPP/7zip/7zip_gcc.mak | 22 + CPP/7zip/Archive/7z/7zCompressionMode.h | 4 + CPP/7zip/Archive/7z/7zDecode.cpp | 24 +- CPP/7zip/Archive/7z/7zEncode.cpp | 4 +- CPP/7zip/Archive/7z/7zHandler.cpp | 42 +- CPP/7zip/Archive/7z/7zHandler.h | 1 + CPP/7zip/Archive/7z/7zHandlerOut.cpp | 26 + CPP/7zip/Archive/7z/7zHeader.h | 6 +- CPP/7zip/Archive/7z/7zIn.cpp | 101 +- CPP/7zip/Archive/7z/7zItem.h | 5 +- CPP/7zip/Archive/7z/7zOut.cpp | 1 + CPP/7zip/Archive/7z/7zUpdate.cpp | 31 +- CPP/7zip/Archive/ApfsHandler.cpp | 4 +- CPP/7zip/Archive/ExtHandler.cpp | 36 +- CPP/7zip/Archive/HfsHandler.cpp | 4 +- CPP/7zip/Archive/LpHandler.cpp | 14 +- CPP/7zip/Archive/LvmHandler.cpp | 3 +- CPP/7zip/Archive/MbrHandler.cpp | 7 +- CPP/7zip/Archive/Nsis/NsisIn.cpp | 6 +- CPP/7zip/Archive/NtfsHandler.cpp | 8 +- CPP/7zip/Archive/PeHandler.cpp | 24 +- CPP/7zip/Archive/SparseHandler.cpp | 4 +- CPP/7zip/Archive/SquashfsHandler.cpp | 7 +- CPP/7zip/Archive/Wim/WimHandlerOut.cpp | 8 +- CPP/7zip/Archive/Wim/WimIn.cpp | 3 + CPP/7zip/Archive/Wim/WimIn.h | 19 +- CPP/7zip/Bundles/Alone/Alone.dsp | 55 + CPP/7zip/Bundles/Alone/makefile | 14 + CPP/7zip/Bundles/Alone/makefile.gcc | 17 + CPP/7zip/Bundles/Alone7z/Alone.dsp | 24 + CPP/7zip/Bundles/Alone7z/makefile | 14 + CPP/7zip/Bundles/Alone7z/makefile.gcc | 17 + CPP/7zip/Bundles/Format7z/makefile | 14 + CPP/7zip/Bundles/Format7zExtract/makefile | 14 + CPP/7zip/Bundles/Format7zF/Arc.mak | 15 +- CPP/7zip/Bundles/Format7zF/Arc_gcc.mak | 11 + CPP/7zip/Bundles/Format7zF/Format7z.dsp | 54 + CPP/7zip/Bundles/SFXCon/SFXCon.dsp | 111 ++ CPP/7zip/Bundles/SFXCon/makefile | 13 + CPP/7zip/Bundles/SFXCon/makefile.gcc | 16 + CPP/7zip/Bundles/SFXWin/SFXWin.dsp | 24 + CPP/7zip/Bundles/SFXWin/makefile | 13 + CPP/7zip/Common/CreateCoder.cpp | 2 +- CPP/7zip/Common/FilterCoder.cpp | 3 + CPP/7zip/Common/FilterCoder.h | 4 + CPP/7zip/Common/MethodProps.h | 3 +- CPP/7zip/Common/PropId.cpp | 4 +- CPP/7zip/Compress/CodecExports.cpp | 2 +- CPP/7zip/Crypto/7zAes.cpp | 140 -- CPP/7zip/Crypto/7zAes.h | 63 +- CPP/7zip/Crypto/7zKeyDerivation.cpp | 159 ++ CPP/7zip/Crypto/7zKeyDerivation.h | 81 ++ CPP/7zip/Crypto/Ascon.cpp | 181 +++ CPP/7zip/Crypto/Ascon.h | 31 + CPP/7zip/Crypto/AsconSimd.h | 156 ++ CPP/7zip/Crypto/Cascade.cpp | 1282 +++++++++++++++++ CPP/7zip/Crypto/Cascade.h | 273 ++++ CPP/7zip/Crypto/CascadeRegister.cpp | 29 + CPP/7zip/Crypto/ChaCha20Simd.h | 731 ++++++++++ CPP/7zip/Crypto/HkdfBlake2sp.cpp | 126 ++ CPP/7zip/Crypto/HkdfBlake2sp.h | 20 + CPP/7zip/Crypto/HmacSha512.cpp | 55 + CPP/7zip/Crypto/HmacSha512.h | 29 + CPP/7zip/Crypto/Pbkdf2HmacSha512.cpp | 63 + CPP/7zip/Crypto/Pbkdf2HmacSha512.h | 20 + CPP/7zip/Crypto/Rar5Aes.h | 19 +- CPP/7zip/Crypto/XChaCha20.cpp | 510 +++++++ CPP/7zip/Crypto/XChaCha20.h | 107 ++ CPP/7zip/Crypto/XChaCha20Poly1305.cpp | 485 +++++++ CPP/7zip/Crypto/XChaCha20Poly1305.h | 117 ++ CPP/7zip/Crypto/XChaCha20Poly1305Register.cpp | 19 + CPP/7zip/Crypto/XChaCha20Register.cpp | 19 + CPP/7zip/IPassword.h | 4 + CPP/7zip/Sha512.mak | 6 + CPP/7zip/UI/Agent/AgentOut.cpp | 1 + CPP/7zip/UI/Agent/AgentProxy.cpp | 48 +- CPP/7zip/UI/Agent/AgentProxy.h | 44 +- CPP/7zip/UI/Common/ArchiveExtractCallback.cpp | 6 + CPP/7zip/UI/Common/LoadCodecs.cpp | 9 +- CPP/7zip/UI/Common/UpdatePair.cpp | 1 + CPP/7zip/UI/Common/UpdatePair.h | 2 +- CPP/7zip/UI/Common/UpdateProduce.cpp | 1 + CPP/7zip/UI/Common/UpdateProduce.h | 28 +- CPP/7zip/UI/Far/FarUtils.cpp | 15 +- CPP/7zip/UI/Far/Plugin.cpp | 15 +- CPP/7zip/UI/FileManager/BrowseDialog2.cpp | 25 +- CPP/7zip/UI/GUI/CompressDialog.cpp | 31 +- CPP/7zip/UI/GUI/CompressDialog.rc | 4 +- CPP/Build.mak | 3 + CPP/Common/Common0.h | 2 +- CPP/Windows/Clipboard.cpp | 2 +- CPP/Windows/CommonDialog.cpp | 2 +- CPP/Windows/Console.h | 2 +- CPP/Windows/Control/ImageList.h | 2 +- CPP/Windows/FileFind.h | 2 - CPP/Windows/FileIO.h | 2 +- CPP/Windows/FileSystem.cpp | 2 +- CPP/Windows/Menu.h | 2 +- CPP/Windows/ProcessUtils.h | 2 +- CPP/Windows/PropVariantConv.cpp | 2 +- CPP/Windows/SecurityUtils.h | 2 +- CPP/Windows/Shell.h | 2 +- CPP/Windows/Synchronization.h | 2 +- CPP/Windows/Thread.h | 2 +- CPP/Windows/TimeUtils.cpp | 2 +- CPP/Windows/{Defs.h => WinDefs.h} | 4 +- CPP/Windows/Window.h | 2 +- DOC/7zip.wxs | 2 +- DOC/Methods.txt | 10 +- DOC/readme.txt | 2 +- DOC/src-history.txt | 5 + 122 files changed, 5857 insertions(+), 854 deletions(-) create mode 100644 CPP/7zip/Crypto/7zKeyDerivation.cpp create mode 100644 CPP/7zip/Crypto/7zKeyDerivation.h create mode 100644 CPP/7zip/Crypto/Ascon.cpp create mode 100644 CPP/7zip/Crypto/Ascon.h create mode 100644 CPP/7zip/Crypto/AsconSimd.h create mode 100644 CPP/7zip/Crypto/Cascade.cpp create mode 100644 CPP/7zip/Crypto/Cascade.h create mode 100644 CPP/7zip/Crypto/CascadeRegister.cpp create mode 100644 CPP/7zip/Crypto/ChaCha20Simd.h create mode 100644 CPP/7zip/Crypto/HkdfBlake2sp.cpp create mode 100644 CPP/7zip/Crypto/HkdfBlake2sp.h create mode 100644 CPP/7zip/Crypto/HmacSha512.cpp create mode 100644 CPP/7zip/Crypto/HmacSha512.h create mode 100644 CPP/7zip/Crypto/Pbkdf2HmacSha512.cpp create mode 100644 CPP/7zip/Crypto/Pbkdf2HmacSha512.h create mode 100644 CPP/7zip/Crypto/XChaCha20.cpp create mode 100644 CPP/7zip/Crypto/XChaCha20.h create mode 100644 CPP/7zip/Crypto/XChaCha20Poly1305.cpp create mode 100644 CPP/7zip/Crypto/XChaCha20Poly1305.h create mode 100644 CPP/7zip/Crypto/XChaCha20Poly1305Register.cpp create mode 100644 CPP/7zip/Crypto/XChaCha20Register.cpp create mode 100644 CPP/7zip/Sha512.mak rename CPP/Windows/{Defs.h => WinDefs.h} (83%) diff --git a/C/7zArcIn.c b/C/7zArcIn.c index 4dc3ba10..f6f6e7c3 100644 --- a/C/7zArcIn.c +++ b/C/7zArcIn.c @@ -11,7 +11,7 @@ #include "CpuArch.h" #define MY_ALLOC(T, p, size, alloc) \ - { if ((p = (T *)ISzAlloc_Alloc(alloc, (size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } + { if ((p = (T *)ISzAlloc_Alloc(alloc, (size_t)(size) * sizeof(T))) == NULL) return SZ_ERROR_MEM; } #define MY_ALLOC_ZE(T, p, size, alloc) \ { if ((size) == 0) p = NULL; else MY_ALLOC(T, p, size, alloc) } @@ -22,8 +22,6 @@ #define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \ { if ((size) == 0) to = NULL; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } } -#define k7zMajorVersion 0 - enum EIdEnum { k7zIdEnd, @@ -52,15 +50,13 @@ enum EIdEnum k7zIdEncodedHeader, k7zIdStartPos, k7zIdDummy - // k7zNtSecure, - // k7zParent, - // k7zIsReal }; const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; #define SzBitUi32s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; } +Z7_FORCE_INLINE static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) { if (num == 0) @@ -76,6 +72,7 @@ static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAllocPtr alloc) return SZ_OK; } +Z7_FORCE_INLINE static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; @@ -84,13 +81,14 @@ static void SzBitUi32s_Free(CSzBitUi32s *p, ISzAllocPtr alloc) #define SzBitUi64s_INIT(p) { (p)->Defs = NULL; (p)->Vals = NULL; } +Z7_FORCE_INLINE static void SzBitUi64s_Free(CSzBitUi64s *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->Defs); p->Defs = NULL; ISzAlloc_Free(alloc, p->Vals); p->Vals = NULL; } - +Z7_NO_INLINE static void SzAr_Init(CSzAr *p) { p->NumPackStreams = 0; @@ -110,23 +108,22 @@ static void SzAr_Init(CSzAr *p) p->RangeLimit = 0; } +Z7_NO_INLINE static void SzAr_Free(CSzAr *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->PackPositions); SzBitUi32s_Free(&p->FolderCRCs, alloc); - ISzAlloc_Free(alloc, p->FoCodersOffsets); ISzAlloc_Free(alloc, p->FoStartPackStreamIndex); ISzAlloc_Free(alloc, p->FoToCoderUnpackSizes); ISzAlloc_Free(alloc, p->FoToMainUnpackSizeIndex); ISzAlloc_Free(alloc, p->CoderUnpackSizes); - ISzAlloc_Free(alloc, p->CodersData); SzAr_Init(p); } - +Z7_NO_INLINE void SzArEx_Init(CSzArEx *p) { SzAr_Init(&p->db); @@ -150,6 +147,7 @@ void SzArEx_Init(CSzArEx *p) SzBitUi64s_INIT(&p->CTime) } +Z7_NO_INLINE void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc) { ISzAlloc_Free(alloc, p->UnpackPositions); @@ -172,15 +170,6 @@ void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc) } -static int TestSignatureCandidate(const Byte *testBytes) -{ - unsigned i; - for (i = 0; i < k7zSignatureSize; i++) - if (testBytes[i] != k7zSignature[i]) - return 0; - return 1; -} - #define SzData_CLEAR(p) { (p)->Data = NULL; (p)->Size = 0; } #define SZ_READ_BYTE_SD_NOCHECK(_sd_, dest) \ @@ -199,14 +188,9 @@ static int TestSignatureCandidate(const Byte *testBytes) #define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } #define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } -#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \ - dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4); - static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) { - Byte firstByte, mask; - unsigned i; - UInt32 v; + unsigned firstByte, mask, i, v; SZ_READ_BYTE(firstByte) if ((firstByte & 0x80) == 0) @@ -223,18 +207,18 @@ static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) SZ_READ_BYTE(mask) *value = v | ((UInt32)mask << 8); mask = 0x20; - for (i = 2; i < 8; i++) + for (i = 2 * 8; i < 8 * 8; i += 8) { - Byte b; + unsigned b; if ((firstByte & mask) == 0) { const UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1); - *value |= (highPart << (8 * i)); + *value |= (highPart << i); return SZ_OK; } - SZ_READ_BYTE(b) - *value |= ((UInt64)b << (8 * i)); mask >>= 1; + SZ_READ_BYTE(b) + *value |= ((UInt64)b << i); } return SZ_OK; } @@ -242,7 +226,7 @@ static Z7_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) static Z7_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) { - Byte firstByte; + unsigned firstByte; UInt64 value64; if (sd->Size == 0) return SZ_ERROR_ARCHIVE; @@ -265,6 +249,7 @@ static Z7_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) #define ReadID(sd, value) ReadNumber(sd, value) +Z7_NO_INLINE static SRes SkipData(CSzData *sd) { UInt64 size; @@ -275,6 +260,7 @@ static SRes SkipData(CSzData *sd) return SZ_OK; } +Z7_NO_INLINE static SRes WaitId(CSzData *sd, UInt32 id) { for (;;) @@ -289,16 +275,8 @@ static SRes WaitId(CSzData *sd, UInt32 id) } } -static SRes RememberBitVector(CSzData *sd, size_t numItems, const Byte **v) -{ - const size_t numBytes = (numItems + 7) >> 3; - if (numBytes > sd->Size) - return SZ_ERROR_ARCHIVE; - *v = sd->Data; - SKIP_DATA(sd, numBytes) - return SZ_OK; -} +Z7_NO_INLINE static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) { unsigned b = 0; @@ -339,8 +317,8 @@ static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, size_t numItems, Byte **v, I memset(v2, 0xFF, (size_t)numBytes); { const unsigned numBits = (unsigned)numItems & 7; - if (numBits != 0) - v2[(size_t)numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); + if (numBits) + v2[(size_t)numBytes - 1] = (Byte)(0xff00u >> numBits); } return SZ_OK; } @@ -348,31 +326,40 @@ static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, size_t numItems, Byte **v, I static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, size_t numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) { size_t i; - CSzData sd; + const Byte *data; + size_t size; UInt32 *vals; const Byte *defs; - MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc) - sd = *sd2; + MY_ALLOC_ZE(UInt32, vals, numItems, alloc) + crcs->Vals = vals; defs = crcs->Defs; - vals = crcs->Vals; + data = sd2->Data; + size = sd2->Size; for (i = 0; i < numItems; i++) if (SzBitArray_Check(defs, i)) { - SZ_READ_32(vals[i]) + if (size < 4) + return SZ_ERROR_ARCHIVE; + size -= 4; + vals[i] = GetUi32(data); + data += 4; } else vals[i] = 0; - *sd2 = sd; + sd2->Data = data; + sd2->Size = size; return SZ_OK; } static SRes ReadBitUi32s(CSzData *sd, size_t numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) { - SzBitUi32s_Free(crcs, alloc); + if (crcs->Defs) + return SZ_ERROR_ARCHIVE; RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)) return ReadUi32s(sd, numItems, crcs, alloc); } +Z7_NO_INLINE static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) { Byte allAreDefined; @@ -395,25 +382,26 @@ static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) { RINOK(SzReadNumber32(sd, &p->NumPackStreams)) - RINOK(WaitId(sd, k7zIdSize)) - MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc) { - UInt64 sum = 0; - UInt32 i; - const UInt32 numPackStreams = p->NumPackStreams; - for (i = 0; i < numPackStreams; i++) + UInt64 *packPositions; + UInt64 sum; + size_t num = (size_t)p->NumPackStreams + 1; + MY_ALLOC(UInt64, packPositions, num, alloc) + p->PackPositions = packPositions; + sum = 0; + for (;;) { UInt64 packSize; - p->PackPositions[i] = sum; + *packPositions++ = sum; + if (--num == 0) + break; RINOK(ReadNumber(sd, &packSize)) sum += packSize; if (sum < packSize) return SZ_ERROR_ARCHIVE; } - p->PackPositions[i] = sum; } - for (;;) { UInt64 type; @@ -430,85 +418,79 @@ static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAllocPtr alloc) } } -/* -static SRes SzReadSwitch(CSzData *sd) -{ - Byte external; - RINOK(SzReadByte(sd, &external)); - return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; -} -*/ #define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) { - UInt32 numCoders, i; - UInt32 numInStreams = 0; - const Byte *dataStart = sd->Data; + UInt32 numCoders, i, numInStreams = 0; + const Byte * const dataStart = sd->Data; - f->NumCoders = 0; - f->NumBonds = 0; - f->NumPackStreams = 0; + // f->NumCoders = 0; + // f->NumBonds = 0; + // f->NumPackStreams = 0; f->UnpackStream = 0; RINOK(SzReadNumber32(sd, &numCoders)) if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) return SZ_ERROR_UNSUPPORTED; + f->NumCoders = numCoders; for (i = 0; i < numCoders; i++) { Byte mainByte; - CSzCoderInfo *coder = f->Coders + i; - unsigned idSize, j; - UInt64 id; - - SZ_READ_BYTE(mainByte) - if ((mainByte & 0xC0) != 0) - return SZ_ERROR_UNSUPPORTED; - - idSize = (unsigned)(mainByte & 0xF); - if (idSize > sizeof(id)) - return SZ_ERROR_UNSUPPORTED; - if (idSize > sd->Size) - return SZ_ERROR_ARCHIVE; - id = 0; - for (j = 0; j < idSize; j++) + CSzCoderInfo *coder; { - id = ((id << 8) | *sd->Data); - sd->Data++; + unsigned idSize, j; + UInt64 id; + const Byte *data; + + if (!sd->Size) + return SZ_ERROR_ARCHIVE; sd->Size--; + data = sd->Data; + mainByte = *data++; + if (mainByte & 0xC0) + return SZ_ERROR_UNSUPPORTED; + idSize = mainByte & 0xF; + if (idSize > sizeof(id)) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd->Size) + return SZ_ERROR_ARCHIVE; + sd->Size -= idSize; + id = 0; + for (j = 0; j < idSize; j++) + id = (id << 8) | *data++; + sd->Data = data; + if (id > (UInt32)0xFFFFFFFF) + return SZ_ERROR_UNSUPPORTED; + coder = f->Coders + i; + coder->MethodID = (UInt32)id; } - if (id > (UInt32)0xFFFFFFFF) - return SZ_ERROR_UNSUPPORTED; - coder->MethodID = (UInt32)id; coder->NumStreams = 1; coder->PropsOffset = 0; coder->PropsSize = 0; - if ((mainByte & 0x10) != 0) + if (mainByte & 0x10) { UInt32 numStreams; - RINOK(SzReadNumber32(sd, &numStreams)) if (numStreams > k_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; coder->NumStreams = (Byte)numStreams; - RINOK(SzReadNumber32(sd, &numStreams)) if (numStreams != 1) return SZ_ERROR_UNSUPPORTED; } numInStreams += coder->NumStreams; - if (numInStreams > k_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; - if ((mainByte & 0x20) != 0) + if (mainByte & 0x20) { - UInt32 propsSize = 0; + UInt32 propsSize; RINOK(SzReadNumber32(sd, &propsSize)) if (propsSize > sd->Size) return SZ_ERROR_ARCHIVE; @@ -521,14 +503,6 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) } } - /* - if (numInStreams == 1 && numCoders == 1) - { - f->NumPackStreams = 1; - f->PackStreams[0] = 0; - } - else - */ { Byte streamUsed[k_NumCodersStreams_in_Folder_MAX]; UInt32 numBonds, numPackStreams; @@ -545,14 +519,13 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) return SZ_ERROR_UNSUPPORTED; f->NumPackStreams = numPackStreams; - for (i = 0; i < numInStreams; i++) + for (i = 0; i < Z7_ARRAY_SIZE(streamUsed); i++) // numInStreams streamUsed[i] = False; - if (numBonds != 0) + if (numBonds) { Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX]; - - for (i = 0; i < numCoders; i++) + for (i = 0; i < Z7_ARRAY_SIZE(coderUsed); i++) // numCoders coderUsed[i] = False; for (i = 0; i < numBonds; i++) @@ -570,24 +543,25 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) coderUsed[bp->OutIndex] = True; } - for (i = 0; i < numCoders; i++) + for (i = 0;;) + { if (!coderUsed[i]) - { - f->UnpackStream = i; break; - } - - if (i == numCoders) - return SZ_ERROR_ARCHIVE; + if (++i == numCoders) + return SZ_ERROR_ARCHIVE; + } + f->UnpackStream = i; } if (numPackStreams == 1) { - for (i = 0; i < numInStreams; i++) + for (i = 0;; i++) + { + if (i == numInStreams) + return SZ_ERROR_ARCHIVE; if (!streamUsed[i]) break; - if (i == numInStreams) - return SZ_ERROR_ARCHIVE; + } f->PackStreams[0] = i; } else @@ -601,40 +575,30 @@ SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd) f->PackStreams[i] = index; } } - - f->NumCoders = numCoders; - return SZ_OK; } -static Z7_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) +static SRes SkipNumbers(CSzData *sd2, UInt32 num) { - CSzData sd; - sd = *sd2; + const Byte *data = sd2->Data; + size_t size = sd2->Size; for (; num != 0; num--) { - Byte firstByte, mask; + unsigned firstByte; unsigned i; - SZ_READ_BYTE_2(firstByte) - if ((firstByte & 0x80) == 0) - continue; - if ((firstByte & 0x40) == 0) - { - if (sd.Size == 0) - return SZ_ERROR_ARCHIVE; - sd.Size--; - sd.Data++; - continue; - } - mask = 0x20; - for (i = 2; i < 8 && (firstByte & mask) != 0; i++) - mask >>= 1; - if (i > sd.Size) + if (size == 0) return SZ_ERROR_ARCHIVE; - SKIP_DATA2(sd, i) + firstByte = *data; + for (i = 1; firstByte & 0x80; i++) + firstByte <<= 1; + if (size < i) + return SZ_ERROR_ARCHIVE; + size -= i; + data += i; } - *sd2 = sd; + sd2->Data = data; + sd2->Size = size; return SZ_OK; } @@ -642,15 +606,10 @@ static Z7_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) #define k_Scan_NumCoders_MAX 64 #define k_Scan_NumCodersStreams_in_Folder_MAX 64 - -static SRes ReadUnpackInfo(CSzAr *p, - CSzData *sd2, - UInt32 numFoldersMax, - const CBuf *tempBufs, UInt32 numTempBufs, - ISzAllocPtr alloc) +static SRes ReadUnpackInfo(CSzAr *p, CSzData *sd2, const UInt32 numFoldersMax, + const CBuf *tempBufs, UInt32 numTempBufs, ISzAllocPtr alloc) { CSzData sd; - UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex; const Byte *startBufPtr; Byte external; @@ -742,15 +701,12 @@ static SRes ReadUnpackInfo(CSzAr *p, { Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX]; Byte coderUsed[k_Scan_NumCoders_MAX]; - UInt32 i; const UInt32 numBonds = numCoders - 1; if (numInStreams < numBonds) return SZ_ERROR_ARCHIVE; - if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX) return SZ_ERROR_UNSUPPORTED; - for (i = 0; i < numInStreams; i++) streamUsed[i] = False; for (i = 0; i < numCoders; i++) @@ -782,16 +738,15 @@ static SRes ReadUnpackInfo(CSzAr *p, return SZ_ERROR_ARCHIVE; streamUsed[index] = True; } - - for (i = 0; i < numCoders; i++) + + for (i = 0;;) + { if (!coderUsed[i]) - { - indexOfMainStream = i; break; - } - - if (i == numCoders) - return SZ_ERROR_ARCHIVE; + if (++i == numCoders) + return SZ_ERROR_ARCHIVE; + } + indexOfMainStream = i; } p->FoStartPackStreamIndex[fo] = packStreamIndex; @@ -806,31 +761,38 @@ static SRes ReadUnpackInfo(CSzAr *p, } } + { + const size_t k_numCodersOutStreams_Limit = (size_t)1 << (sizeof(size_t) * 8 - 4); + if (numCodersOutStreams >= k_numCodersOutStreams_Limit) + return SZ_ERROR_UNSUPPORTED; + } p->FoToCoderUnpackSizes[fo] = numCodersOutStreams; - + p->FoStartPackStreamIndex[fo] = packStreamIndex; { const size_t dataSize = (size_t)(sd.Data - startBufPtr); - p->FoStartPackStreamIndex[fo] = packStreamIndex; p->FoCodersOffsets[fo] = dataSize; MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc) } - if (external != 0) + if (external) { - if (sd.Size != 0) + if (sd.Size) return SZ_ERROR_ARCHIVE; sd = *sd2; } RINOK(WaitId(&sd, k7zIdCodersUnpackSize)) - - MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc) { - UInt32 i; - for (i = 0; i < numCodersOutStreams; i++) - { - RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)) - } + UInt64 *sizes; + MY_ALLOC_ZE(UInt64, sizes, (size_t)numCodersOutStreams, alloc) + p->CoderUnpackSizes = sizes; + if (numCodersOutStreams) + do + { + RINOK(ReadNumber(&sd, sizes)) + sizes++; + } + while (--numCodersOutStreams); } for (;;) @@ -838,10 +800,7 @@ static SRes ReadUnpackInfo(CSzAr *p, UInt64 type; RINOK(ReadID(&sd, &type)) if (type == k7zIdEnd) - { - *sd2 = sd; - return SZ_OK; - } + break; if (type == k7zIdCRC) { RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)) @@ -849,6 +808,8 @@ static SRes ReadUnpackInfo(CSzAr *p, } RINOK(SkipData(&sd)) } + *sd2 = sd; + return SZ_OK; } @@ -868,12 +829,12 @@ typedef struct } CSubStreamInfo; -static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) +static SRes ReadSubStreamsInfo(const CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { UInt64 type = 0; - UInt32 numSubDigests = 0; const UInt32 numFolders = p->NumFolders; UInt32 numUnpackStreams = numFolders; + UInt32 numSubDigests = numFolders; UInt32 numUnpackSizesInData = 0; for (;;) @@ -882,6 +843,8 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) if (type == k7zIdNumUnpackStream) { UInt32 i; + if (ssi->sdNumSubStreams.Data) + return SZ_ERROR_UNSUPPORTED; ssi->sdNumSubStreams.Data = sd->Data; numUnpackStreams = 0; numSubDigests = 0; @@ -889,10 +852,10 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) { UInt32 numStreams; RINOK(SzReadNumber32(sd, &numStreams)) - if (numUnpackStreams > numUnpackStreams + numStreams) - return SZ_ERROR_UNSUPPORTED; numUnpackStreams += numStreams; - if (numStreams != 0) + if (numUnpackStreams < numStreams) + return SZ_ERROR_UNSUPPORTED; + if (numStreams) numUnpackSizesInData += (numStreams - 1); if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) numSubDigests += numStreams; @@ -905,12 +868,8 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) RINOK(SkipData(sd)) } - if (!ssi->sdNumSubStreams.Data) - { - numSubDigests = numFolders; - if (p->FolderCRCs.Defs) - numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); - } + if (!ssi->sdNumSubStreams.Data && p->FolderCRCs.Defs) + numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); ssi->NumTotalSubStreams = numUnpackStreams; ssi->NumSubDigests = numSubDigests; @@ -929,6 +888,8 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) return SZ_OK; if (type == k7zIdCRC) { + if (ssi->sdCRCs.Data) + return SZ_ERROR_UNSUPPORTED; ssi->sdCRCs.Data = sd->Data; RINOK(SkipBitUi32s(sd, numSubDigests)) ssi->sdCRCs.Size = (size_t)(sd->Data - ssi->sdCRCs.Data); @@ -941,9 +902,11 @@ static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) } } + static SRes SzReadStreamsInfo(CSzAr *p, CSzData *sd, - UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, + const UInt32 numFoldersMax, + const CBuf * const tempBufs, const UInt32 numTempBufs, UInt64 *dataOffset, CSubStreamInfo *ssi, ISzAllocPtr alloc) @@ -985,12 +948,13 @@ static SRes SzReadStreamsInfo(CSzAr *p, return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED); } + static SRes SzReadAndDecodePackedStreams( ILookInStreamPtr inStream, CSzData *sd, - CBuf *tempBufs, - UInt32 numFoldersMax, - UInt64 baseOffset, + CBuf * const tempBufs, + const UInt32 numFoldersMax, + const UInt64 baseOffset, CSzAr *p, ISzAllocPtr allocTemp) { @@ -1027,6 +991,7 @@ static SRes SzReadAndDecodePackedStreams( return SZ_OK; } + // (size & 1) == 0 // (data) is aligned for 2-bytes static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) @@ -1053,30 +1018,35 @@ static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size return (p == lim) ? SZ_OK : SZ_ERROR_ARCHIVE; } -static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, size_t num, - CSzData *sd2, - const CBuf *tempBufs, UInt32 numTempBufs, - ISzAllocPtr alloc) + +static SRes ReadTime(CSzBitUi64s *p, size_t num, CSzData *sd2, + const CBuf *tempBufs, UInt32 numTempBufs, ISzAllocPtr alloc) { - CSzData sd; + const Byte *data; + size_t size; size_t i; CNtfsFileTime *vals; Byte *defs; Byte external; + if (p->Defs) + return SZ_ERROR_ARCHIVE; RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)) SZ_READ_BYTE_SD(sd2, external) if (external == 0) - sd = *sd2; + { + data = sd2->Data; + size = sd2->Size; + } else { UInt32 index; RINOK(SzReadNumber32(sd2, &index)) - if (index >= numTempBufs) + if (index >= numTempBufs || sd2->Size) return SZ_ERROR_ARCHIVE; - sd.Data = tempBufs[index].data; - sd.Size = tempBufs[index].size; + data = tempBufs[index].data; + size = tempBufs[index].size; } MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc) @@ -1085,18 +1055,18 @@ static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, size_t num, for (i = 0; i < num; i++) if (SzBitArray_Check(defs, i)) { - if (sd.Size < 8) + if (size < 8) return SZ_ERROR_ARCHIVE; - vals[i].Low = GetUi32(sd.Data); - vals[i].High = GetUi32(sd.Data + 4); - SKIP_DATA2(sd, 8) + size -= 8; + vals[i].Low = GetUi32(data); + vals[i].High = GetUi32(data + 4); + data += 8; } else vals[i].High = vals[i].Low = 0; - if (external == 0) - *sd2 = sd; - + if (size) + return SZ_ERROR_ARCHIVE; return SZ_OK; } @@ -1104,16 +1074,11 @@ static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, size_t num, #define NUM_ADDITIONAL_STREAMS_MAX 8 -static SRes SzReadHeader2( - CSzArEx *p, /* allocMain */ - CSzData *sd, - ILookInStreamPtr inStream, - CBuf *tempBufs, UInt32 *numTempBufs, - ISzAllocPtr allocMain, - ISzAllocPtr allocTemp - ) +static SRes SzReadHeader2(CSzArEx *p, CSzData *sd, ILookInStreamPtr inStream, + CBuf * const tempBufs, ISzAllocPtr allocMain, ISzAllocPtr allocTemp) { CSubStreamInfo ssi; + UInt32 numTempBufs = 0; { UInt64 type; @@ -1150,7 +1115,7 @@ static SRes SzReadHeader2( res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, p->startPosAfterHeader, &tempAr, allocTemp); - *numTempBufs = tempAr.NumFolders; + numTempBufs = tempAr.NumFolders; SzAr_Free(&tempAr, allocTemp); if (res != SZ_OK) @@ -1160,24 +1125,21 @@ static SRes SzReadHeader2( if (type == k7zIdMainStreamsInfo) { - RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs, + static const UInt32 k_numFoldersMax = (UInt32)1 << 30; + RINOK(SzReadStreamsInfo(&p->db, sd, k_numFoldersMax, tempBufs, numTempBufs, &p->dataPos, &ssi, allocMain)) p->dataPos += p->startPosAfterHeader; RINOK(ReadID(sd, &type)) } if (type == k7zIdEnd) - { return SZ_OK; - } - if (type != k7zIdFilesInfo) return SZ_ERROR_ARCHIVE; } { - UInt32 numFiles = 0; - UInt32 numEmptyStreams = 0; + UInt32 numFiles, numEmptyStreams = 0; const Byte *emptyStreams = NULL; const Byte *emptyFiles = NULL; @@ -1186,44 +1148,68 @@ static SRes SzReadHeader2( for (;;) { + CSzData sdSwitch; UInt64 type; - UInt64 size; RINOK(ReadID(sd, &type)) if (type == k7zIdEnd) break; - RINOK(ReadNumber(sd, &size)) - if (size > sd->Size) - return SZ_ERROR_ARCHIVE; - - if (type >= ((UInt32)1 << 8)) { + UInt64 size; + RINOK(ReadNumber(sd, &size)) + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + sdSwitch.Data = sd->Data; + sdSwitch.Size = (size_t)size; SKIP_DATA(sd, size) } - else switch ((unsigned)type) + if (type >= 64) + continue; + + switch ((unsigned)type) { + case k7zIdEmptyStream: + { + if (emptyStreams || emptyFiles) + return SZ_ERROR_ARCHIVE; + if ((numFiles + 7) >> 3 != sdSwitch.Size) + return SZ_ERROR_ARCHIVE; + emptyStreams = sdSwitch.Data; + numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); + break; + } + + case k7zIdEmptyFile: + { + if (emptyFiles) + return SZ_ERROR_ARCHIVE; + if ((numEmptyStreams + 7) >> 3 != sdSwitch.Size) + return SZ_ERROR_ARCHIVE; + emptyFiles = sdSwitch.Data; + break; + } + case k7zIdName: { size_t namesSize; const Byte *namesData; Byte external; - - SZ_READ_BYTE(external) + if (p->FileNameOffsets) + return SZ_ERROR_ARCHIVE; + SZ_READ_BYTE_SD(&sdSwitch, external) if (external == 0) { - namesSize = (size_t)size - 1; - namesData = sd->Data; - SKIP_DATA(sd, namesSize) + namesData = sdSwitch.Data; + namesSize = sdSwitch.Size; } else { UInt32 index; - RINOK(SzReadNumber32(sd, &index)) - if (index >= *numTempBufs) + RINOK(SzReadNumber32(&sdSwitch, &index)) + if (index >= numTempBufs || sdSwitch.Size) return SZ_ERROR_ARCHIVE; - namesData = (tempBufs)[index].data; - namesSize = (tempBufs)[index].size; + namesData = tempBufs[index].data; + namesSize = tempBufs[index].size; } - if (namesSize & 1) return SZ_ERROR_ARCHIVE; MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain) @@ -1231,58 +1217,38 @@ static SRes SzReadHeader2( RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) break; } - case k7zIdEmptyStream: - { - RINOK(RememberBitVector(sd, numFiles, &emptyStreams)) - numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); - emptyFiles = NULL; - break; - } - case k7zIdEmptyFile: - { - RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)) - break; - } + case k7zIdWinAttrib: { Byte external; - CSzData sdSwitch; - CSzData *sdPtr; - SzBitUi32s_Free(&p->Attribs, allocMain); - RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)) - - SZ_READ_BYTE(external) - if (external == 0) - sdPtr = sd; - else + if (p->Attribs.Defs) + return SZ_ERROR_ARCHIVE; + RINOK(ReadBitVector(&sdSwitch, numFiles, &p->Attribs.Defs, allocMain)) + SZ_READ_BYTE_SD(&sdSwitch, external) + if (external) { UInt32 index; - RINOK(SzReadNumber32(sd, &index)) - if (index >= *numTempBufs) + RINOK(SzReadNumber32(&sdSwitch, &index)) + if (index >= numTempBufs || sdSwitch.Size) return SZ_ERROR_ARCHIVE; - sdSwitch.Data = (tempBufs)[index].data; - sdSwitch.Size = (tempBufs)[index].size; - sdPtr = &sdSwitch; + sdSwitch.Data = tempBufs[index].data; + sdSwitch.Size = tempBufs[index].size; } - RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)) + RINOK(ReadUi32s(&sdSwitch, numFiles, &p->Attribs, allocMain)) + if (sdSwitch.Size) + return SZ_ERROR_ARCHIVE; break; } - /* - case k7zParent: + + case k7zIdMTime: + case k7zIdCTime: { - SzBitUi32s_Free(&p->Parents, allocMain); - RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain)); - RINOK(SzReadSwitch(sd)); - RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain)); + RINOK(ReadTime((unsigned)type == k7zIdMTime ? &p->MTime: &p->CTime, + numFiles, &sdSwitch, tempBufs, numTempBufs, allocMain)) break; } - */ - case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break; - case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)) break; - default: - { - SKIP_DATA(sd, size) - } + + default: break; } } @@ -1481,25 +1447,19 @@ static SRes SzReadHeader( ISzAllocPtr allocTemp) { UInt32 i; - UInt32 numTempBufs = 0; SRes res; CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX]; for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) Buf_Init(tempBufs + i); - res = SzReadHeader2(p, sd, inStream, - tempBufs, &numTempBufs, - allocMain, allocTemp); + res = SzReadHeader2(p, sd, inStream, tempBufs, allocMain, allocTemp); for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) Buf_Free(tempBufs + i, allocTemp); - RINOK(res) - - if (sd->Size != 0) - return SZ_ERROR_FAIL; - + if (res == SZ_OK && sd->Size != 0) + return SZ_ERROR_ARCHIVE; return res; } @@ -1510,53 +1470,52 @@ static SRes SzArEx_Open2( ISzAllocPtr allocTemp) { Byte header[k7zStartHeaderSize]; - Int64 startArcPos; + Int64 startPosAfterHeader; UInt64 nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; UInt32 nextHeaderCRC; CBuf buf; SRes res; - startArcPos = 0; - RINOK(ILookInStream_Seek(inStream, &startArcPos, SZ_SEEK_CUR)) - RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)) - - if (!TestSignatureCandidate(header)) - return SZ_ERROR_NO_ARCHIVE; - if (header[6] != k7zMajorVersion) - return SZ_ERROR_UNSUPPORTED; + startPosAfterHeader = 0; // k7zStartHeaderSize + RINOK(ILookInStream_Seek(inStream, &startPosAfterHeader, SZ_SEEK_CUR)) + p->startPosAfterHeader = (UInt64)startPosAfterHeader; + { + unsigned i; + for (i = 0; i < k7zSignatureSize; i++) + if (header[i] != k7zSignature[i]) + return SZ_ERROR_NO_ARCHIVE; + if (header[6] != 0) // k7zMajorVersion + return SZ_ERROR_UNSUPPORTED; + } + if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) + return SZ_ERROR_CRC; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); - p->startPosAfterHeader = (UInt64)startArcPos + k7zStartHeaderSize; - - if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) - return SZ_ERROR_CRC; - p->db.RangeLimit = nextHeaderOffset; - + if (nextHeaderOffset >= (UInt64)1 << 62 || + nextHeaderSize >= (UInt64)1 << 48) + return SZ_ERROR_NO_ARCHIVE; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) + { + if (nextHeaderOffset != 0 || nextHeaderCRC != 0) + return SZ_ERROR_NO_ARCHIVE; return SZ_OK; - if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || - nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) - return SZ_ERROR_NO_ARCHIVE; - + } { Int64 pos = 0; RINOK(ILookInStream_Seek(inStream, &pos, SZ_SEEK_END)) - if ((UInt64)pos < (UInt64)startArcPos + nextHeaderOffset || - (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + if ((UInt64)(pos - startPosAfterHeader) < nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } - - RINOK(LookInStream_SeekTo(inStream, (UInt64)startArcPos + k7zStartHeaderSize + nextHeaderOffset)) + RINOK(LookInStream_SeekTo(inStream, (UInt64)startPosAfterHeader + nextHeaderOffset)) if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; @@ -1720,61 +1679,23 @@ SRes SzArEx_Extract( size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) { - const size_t offs = p->FileNameOffsets[fileIndex]; - const size_t len = p->FileNameOffsets[fileIndex + 1] - offs; - if (dest != 0) + const size_t * const offsets = p->FileNameOffsets; + if (!offsets) { - size_t i; - const Byte *src = p->FileNames + offs * 2; - for (i = 0; i < len; i++) - dest[i] = GetUi16(src + i * 2); - } - return len; -} - -/* -size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex) -{ - size_t len; - if (!p->FileNameOffsets) + if (dest) + *dest = 0; return 1; - len = 0; - for (;;) - { - UInt32 parent = (UInt32)(Int32)-1; - len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; - if SzBitWithVals_Check(&p->Parents, fileIndex) - parent = p->Parents.Vals[fileIndex]; - if (parent == (UInt32)(Int32)-1) - return len; - fileIndex = parent; } -} - -UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest) -{ - BoolInt needSlash; - if (!p->FileNameOffsets) - { - *(--dest) = 0; - return dest; - } - needSlash = False; - for (;;) { - UInt32 parent = (UInt32)(Int32)-1; - size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; - SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen); - if (needSlash) - *(dest - 1) = '/'; - needSlash = True; - dest -= curLen; - - if SzBitWithVals_Check(&p->Parents, fileIndex) - parent = p->Parents.Vals[fileIndex]; - if (parent == (UInt32)(Int32)-1) - return dest; - fileIndex = parent; + const size_t offs = offsets[fileIndex]; + const size_t len = offsets[fileIndex + 1] - offs; + if (dest) + { + size_t i; + const Byte *src = p->FileNames + offs * 2; + for (i = 0; i < len; i++) + dest[i] = GetUi16a(src + i * 2); + } + return len; } } -*/ diff --git a/C/7zVersion.h b/C/7zVersion.h index 387a91c0..50ccebb4 100644 --- a/C/7zVersion.h +++ b/C/7zVersion.h @@ -1,7 +1,7 @@ #define MY_VER_MAJOR 26 -#define MY_VER_MINOR 1 +#define MY_VER_MINOR 2 #define MY_VER_BUILD 0 -#define MY_VERSION_NUMBERS "26.01" +#define MY_VERSION_NUMBERS "26.02" #define MY_VERSION MY_VERSION_NUMBERS #ifdef MY_CPU_NAME @@ -10,7 +10,7 @@ #define MY_VERSION_CPU MY_VERSION #endif -#define MY_DATE "2026-04-27" +#define MY_DATE "2026-06-25" #undef MY_COPYRIGHT #undef MY_VERSION_COPYRIGHT_DATE #define MY_AUTHOR_NAME "Igor Pavlov" diff --git a/C/Compiler.h b/C/Compiler.h index a3577b25..c06b8836 100644 --- a/C/Compiler.h +++ b/C/Compiler.h @@ -76,6 +76,11 @@ #pragma GCC diagnostic ignored "-Wreserved-identifier" #endif +#if __clang_major__ >= 22 +// for "StdAfx.h" and "Precomp.h" +#pragma GCC diagnostic ignored "-Wshadow-header" +#endif + #endif // __clang__ #if defined(__clang__) && __clang_major__ >= 16 diff --git a/C/DllSecur.c b/C/DllSecur.c index bbbfc0a7..d3852593 100644 --- a/C/DllSecur.c +++ b/C/DllSecur.c @@ -1,5 +1,5 @@ /* DllSecur.c -- DLL loading security -2023-12-03 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -67,7 +67,7 @@ void LoadSecurityDlls(void) // at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ??? IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN { - wchar_t buf[MAX_PATH + 100]; + WCHAR buf[MAX_PATH + 100]; const char *dll; unsigned pos = GetSystemDirectoryW(buf, MAX_PATH + 2); if (pos == 0 || pos > MAX_PATH) @@ -76,7 +76,7 @@ void LoadSecurityDlls(void) buf[pos++] = '\\'; for (dll = g_Dlls; *dll != 0;) { - wchar_t *dest = &buf[pos]; + WCHAR *dest = &buf[pos]; for (;;) { const char c = *dll++; diff --git a/C/MtDec.c b/C/MtDec.c index 96274b6f..71fc1eef 100644 --- a/C/MtDec.c +++ b/C/MtDec.c @@ -1,5 +1,5 @@ /* MtDec.c -- Multi-thread Decoder -2024-02-20 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -22,7 +22,7 @@ #define PRF(x) #endif -#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d);) void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress) { diff --git a/C/Util/7z/7zMain.c b/C/Util/7z/7zMain.c index 7048b661..300c3639 100644 --- a/C/Util/7z/7zMain.c +++ b/C/Util/7z/7zMain.c @@ -960,7 +960,12 @@ int Z7_CDECL main(int numargs, char *args[]) if (listCommand == 0 && isDir && !fullPaths) continue; len = SzArEx_GetFileNameUtf16(&db, i, NULL); - // len = SzArEx_GetFullNameLen(&db, i); + + if (len > (1u << 20)) + { + res = SZ_ERROR_UNSUPPORTED; + break; + } if (len > tempSize) { diff --git a/C/Util/7zipInstall/7zipInstall.c b/C/Util/7zipInstall/7zipInstall.c index 7d8e8c42..ce30732d 100644 --- a/C/Util/7zipInstall/7zipInstall.c +++ b/C/Util/7zipInstall/7zipInstall.c @@ -1,5 +1,5 @@ /* 7zipInstall.c - 7-Zip Installer -2024-04-05 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -142,7 +142,7 @@ static WCHAR path[MAX_PATH * 2 + 40]; -static void CpyAscii(wchar_t *dest, const char *s) +static void CpyAscii(WCHAR *dest, const char *s) { for (;;) { @@ -153,13 +153,13 @@ static void CpyAscii(wchar_t *dest, const char *s) } } -static void CatAscii(wchar_t *dest, const char *s) +static void CatAscii(WCHAR *dest, const char *s) { dest += wcslen(dest); CpyAscii(dest, s); } -static void PrintErrorMessage(const char *s1, const wchar_t *s2) +static void PrintErrorMessage(const char *s1, const WCHAR *s2) { WCHAR m[MAX_PATH + 512]; m[0] = 0; @@ -196,7 +196,7 @@ static DWORD GetFileVersion(LPCWSTR s) if (!g_version_dll_hModule) { - wchar_t buf[MAX_PATH + 100]; + WCHAR buf[MAX_PATH + 100]; { unsigned len = GetSystemDirectoryW(buf, MAX_PATH + 2); if (len == 0 || len > MAX_PATH) @@ -255,13 +255,13 @@ static WRes MyCreateDir(LPCWSTR name) #define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) #define IS_DRIVE_PATH(s) (IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2])) -static int ReverseFind_PathSepar(const wchar_t *s) +static int ReverseFind_PathSepar(const WCHAR *s) { int separ = -1; int i; for (i = 0;; i++) { - wchar_t c = s[i]; + WCHAR c = s[i]; if (c == 0) return separ; if (IS_SEPAR(c)) @@ -566,7 +566,7 @@ static void NormalizePrefix(WCHAR *s) for (;; i++) { - const wchar_t c = s[i]; + const WCHAR c = s[i]; if (c == 0) break; if (c == '/') @@ -587,10 +587,10 @@ static char MyCharLower_Ascii(char c) return c; } -static wchar_t MyWCharLower_Ascii(wchar_t c) +static WCHAR MyWCharLower_Ascii(WCHAR c) { if (c >= 'A' && c <= 'Z') - return (wchar_t)(c + 0x20); + return (WCHAR)(c + 0x20); return c; } @@ -976,13 +976,13 @@ static void WriteShellEx(void) } -static const wchar_t *GetCmdParam(const wchar_t *s) +static const WCHAR *GetCmdParam(const WCHAR *s) { unsigned pos = 0; BoolInt quoteMode = False; for (;; s++) { - wchar_t c = *s; + WCHAR c = *s; if (c == 0 || (c == L' ' && !quoteMode)) break; if (c == L'\"') @@ -999,12 +999,12 @@ static const wchar_t *GetCmdParam(const wchar_t *s) } -static void RemoveQuotes(wchar_t *s) +static void RemoveQuotes(WCHAR *s) { - const wchar_t *src = s; + const WCHAR *src = s; for (;;) { - wchar_t c = *src++; + WCHAR c = *src++; if (c == '\"') continue; *s++ = c; @@ -1039,7 +1039,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, CrcGenerateTable(); { - const wchar_t *s = GetCommandLineW(); + const WCHAR *s = GetCommandLineW(); #ifndef UNDER_CE s = GetCmdParam(s); @@ -1048,7 +1048,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, for (;;) { { - const wchar_t c = *s; + const WCHAR c = *s; if (c == 0) break; if (c == ' ') @@ -1059,7 +1059,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } { - const wchar_t *s2 = GetCmdParam(s); + const WCHAR *s2 = GetCmdParam(s); BoolInt error = True; if (cmd[0] == '/') { @@ -1315,7 +1315,7 @@ if (res == SZ_OK) for (;;) { - const wchar_t c = path[i++]; + const WCHAR c = path[i++]; if (c == 0) break; if (c != ' ') diff --git a/C/Util/7zipUninstall/7zipUninstall.c b/C/Util/7zipUninstall/7zipUninstall.c index e7051e25..2c1333ba 100644 --- a/C/Util/7zipUninstall/7zipUninstall.c +++ b/C/Util/7zipUninstall/7zipUninstall.c @@ -1,5 +1,5 @@ /* 7zipUninstall.c - 7-Zip Uninstaller -2024-03-21 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -147,7 +147,7 @@ static LPCWSTR const kUninstallExe = L"Uninstall.exe"; #define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) - 0x20 : (c))) -static void CpyAscii(wchar_t *dest, const char *s) +static void CpyAscii(WCHAR *dest, const char *s) { for (;;) { @@ -158,13 +158,13 @@ static void CpyAscii(wchar_t *dest, const char *s) } } -static void CatAscii(wchar_t *dest, const char *s) +static void CatAscii(WCHAR *dest, const char *s) { dest += wcslen(dest); CpyAscii(dest, s); } -static void PrintErrorMessage(const char *s1, const wchar_t *s2) +static void PrintErrorMessage(const char *s1, const WCHAR *s2) { WCHAR m[MAX_PATH + 512]; m[0] = 0; @@ -183,12 +183,12 @@ static void PrintErrorMessage(const char *s1, const wchar_t *s2) } -static BoolInt AreStringsEqual_NoCase(const wchar_t *s1, const wchar_t *s2) +static BoolInt AreStringsEqual_NoCase(const WCHAR *s1, const WCHAR *s2) { for (;;) { - wchar_t c1 = *s1++; - wchar_t c2 = *s2++; + WCHAR c1 = *s1++; + WCHAR c2 = *s2++; if (c1 != c2 && MAKE_CHAR_UPPER(c1) != MAKE_CHAR_UPPER(c2)) return False; if (c2 == 0) @@ -196,12 +196,12 @@ static BoolInt AreStringsEqual_NoCase(const wchar_t *s1, const wchar_t *s2) } } -static BoolInt IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) +static BoolInt IsString1PrefixedByString2_NoCase(const WCHAR *s1, const WCHAR *s2) { for (;;) { - wchar_t c1; - const wchar_t c2 = *s2++; + WCHAR c1; + const WCHAR c2 = *s2++; if (c2 == 0) return True; c1 = *s1++; @@ -446,7 +446,7 @@ static LPCWSTR const k_AppPaths_7zFm = L"Software\\Microsoft\\Windows\\CurrentVe static LPCWSTR const k_Uninstall_7zip = k_REG_Uninstall L"7-Zip"; -static void RemoveQuotes(wchar_t *s) +static void RemoveQuotes(WCHAR *s) { const size_t len = wcslen(s); size_t i; @@ -457,7 +457,7 @@ static void RemoveQuotes(wchar_t *s) s[len - 2] = 0; } -static BoolInt AreEqual_Path_PrefixName(const wchar_t *s, const wchar_t *prefix, const wchar_t *name) +static BoolInt AreEqual_Path_PrefixName(const WCHAR *s, const WCHAR *prefix, const WCHAR *name) { if (!IsString1PrefixedByString2_NoCase(s, prefix)) return False; @@ -558,13 +558,13 @@ static void WriteCLSID(void) } -static const wchar_t *GetCmdParam(const wchar_t *s) +static const WCHAR *GetCmdParam(const WCHAR *s) { unsigned pos = 0; BoolInt quoteMode = False; for (;; s++) { - const wchar_t c = *s; + const WCHAR c = *s; if (c == 0 || (c == L' ' && !quoteMode)) break; if (c == L'\"') @@ -581,12 +581,12 @@ static const wchar_t *GetCmdParam(const wchar_t *s) } /* -static void RemoveQuotes(wchar_t *s) +static void RemoveQuotes(WCHAR *s) { - const wchar_t *src = s; + const WCHAR *src = s; for (;;) { - wchar_t c = *src++; + WCHAR c = *src++; if (c == '\"') continue; *s++ = c; @@ -618,11 +618,11 @@ static BOOL RemoveFileAfterReboot(void) // #define IS_LIMIT_CHAR(c) (c == 0 || c == ' ') -static BoolInt IsThereSpace(const wchar_t *s) +static BoolInt IsThereSpace(const WCHAR *s) { for (;;) { - const wchar_t c = *s++; + const WCHAR c = *s++; if (c == 0) return False; if (c == ' ') @@ -630,7 +630,7 @@ static BoolInt IsThereSpace(const wchar_t *s) } } -static void AddPathParam(wchar_t *dest, const wchar_t *src) +static void AddPathParam(WCHAR *dest, const WCHAR *src) { const BoolInt needQuote = IsThereSpace(src); if (needQuote) @@ -937,7 +937,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, #endif lpCmdLine, int nCmdShow) { - const wchar_t *cmdParams; + const WCHAR *cmdParams; BoolInt useTemp = True; UNUSED_VAR(hPrevInstance) @@ -957,7 +957,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, #endif { - const wchar_t *s = GetCommandLineW(); + const WCHAR *s = GetCommandLineW(); #ifndef UNDER_CE s = GetCmdParam(s); @@ -968,7 +968,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, for (;;) { { - wchar_t c = *s; + WCHAR c = *s; if (c == 0) break; if (c == ' ') @@ -979,7 +979,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } { - const wchar_t *s2 = GetCmdParam(s); + const WCHAR *s2 = GetCmdParam(s); BoolInt error = True; if (cmd[0] == '/') { @@ -1022,7 +1022,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } { - wchar_t *name; + WCHAR *name; const DWORD len = GetModuleFileNameW(NULL, modulePath, MAX_PATH); if (len == 0 || len > MAX_PATH) return 1; @@ -1031,10 +1031,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wcscpy(modulePrefix, modulePath); { - wchar_t *s = modulePrefix; + WCHAR *s = modulePrefix; for (;;) { - const wchar_t c = *s++; + const WCHAR c = *s++; if (c == 0) break; if (c == WCHAR_PATH_SEPARATOR) @@ -1079,14 +1079,14 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, CpyAscii(path + pathLen, "7z"); { - wchar_t *s = path + wcslen(path); + WCHAR *s = path + wcslen(path); UInt32 value = d; unsigned k; for (k = 0; k < 8; k++) { const unsigned t = value & 0xF; value >>= 4; - s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + s[7 - k] = (WCHAR)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[k] = 0; } diff --git a/C/Util/SfxSetup/SfxSetup.c b/C/Util/SfxSetup/SfxSetup.c index 9b5c1f91..344aa735 100644 --- a/C/Util/SfxSetup/SfxSetup.c +++ b/C/Util/SfxSetup/SfxSetup.c @@ -1,5 +1,5 @@ /* SfxSetup.c - 7z SFX Setup -2024-01-24 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -54,7 +54,7 @@ static const char * const kNames[] = , "start" }; -static unsigned FindExt(const wchar_t *s, unsigned *extLen) +static unsigned FindExt(const WCHAR *s, unsigned *extLen) { unsigned len = (unsigned)wcslen(s); unsigned i; @@ -72,7 +72,7 @@ static unsigned FindExt(const wchar_t *s, unsigned *extLen) #define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) - 0x20 : (c))) -static unsigned FindItem(const char * const *items, unsigned num, const wchar_t *s, unsigned len) +static unsigned FindItem(const char * const *items, unsigned num, const WCHAR *s, unsigned len) { unsigned i; for (i = 0; i < num; i++) @@ -268,7 +268,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, #endif size_t pathLen; DWORD winRes; - const wchar_t *cmdLineParams; + const WCHAR *cmdLineParams; const char *errorMessage = NULL; BoolInt useShellExecute = True; DWORD exitCode = 0; @@ -306,7 +306,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, BoolInt quoteMode = False; for (;; cmdLineParams++) { - const wchar_t c = *cmdLineParams; + const WCHAR c = *cmdLineParams; if (c == L'\"') quoteMode = !quoteMode; else if (c == 0 || (c == L' ' && !quoteMode)) @@ -335,14 +335,14 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, wcscpy(path + pathLen, L"7z"); { - wchar_t *s = path + wcslen(path); + WCHAR *s = path + wcslen(path); UInt32 value = d; unsigned k; for (k = 0; k < 8; k++) { const unsigned t = value & 0xF; value >>= 4; - s[7 - k] = (wchar_t)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + s[7 - k] = (WCHAR)((t < 10) ? ('0' + t) : ('A' + (t - 10))); } s[k] = '\0'; } diff --git a/C/XzDec.c b/C/XzDec.c index fe6b425a..e4ae1448 100644 --- a/C/XzDec.c +++ b/C/XzDec.c @@ -25,8 +25,8 @@ #define PRF(x) #endif -#define PRF_STR(s) PRF(printf("\n" s "\n")) -#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) +#define PRF_STR(s) PRF(printf("\n" s "\n");) +#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d);) #include #include @@ -574,7 +574,7 @@ static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 m output (status) can be : CODER_STATUS_NOT_FINISHED CODER_STATUS_FINISHED_WITH_MARK - CODER_STATUS_NEEDS_MORE_INPUT - not implemented still + CODER_STATUS_NEEDS_MORE_INPUT */ static SRes MixCoder_Code(CMixCoder *p, @@ -582,8 +582,8 @@ static SRes MixCoder_Code(CMixCoder *p, const Byte *src, SizeT *srcLen, int srcWasFinished, ECoderFinishMode finishMode) { - SizeT destLenOrig = *destLen; - SizeT srcLenOrig = *srcLen; + const SizeT destLenOrig = *destLen; + const SizeT srcLenOrig = *srcLen; *destLen = 0; *srcLen = 0; @@ -597,39 +597,26 @@ static SRes MixCoder_Code(CMixCoder *p, if (p->outBuf) { SRes res; - SizeT destLen2, srcLen2; + SizeT destLen2; int wasFinished; PRF_STR("------- MixCoder Single ----------") - srcLen2 = srcLenOrig; destLen2 = destLenOrig; - + if (p->numCoders != 1) { - IStateCoder *coder = &p->coders[0]; - res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode, - // &wasFinished, - &p->status); - wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK); + if (destLen2 < p->outWritten) + return SZ_ERROR_FAIL; + destLen2 -= p->outWritten; } - - p->res = res; - - /* - if (wasFinished) - p->status = CODER_STATUS_FINISHED_WITH_MARK; - else + *srcLen = srcLenOrig; { - if (res == SZ_OK) - if (destLen2 != destLenOrig) - p->status = CODER_STATUS_NEEDS_MORE_INPUT; + IStateCoder *coder = &p->coders[0]; + res = coder->Code2(coder->p, NULL, &destLen2, src, srcLen, srcWasFinished, finishMode, &p->status); } - */ - - - *srcLen = srcLen2; - src += srcLen2; + p->res = res; p->outWritten += destLen2; + wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK); if (res != SZ_OK || srcWasFinished || wasFinished) p->wasFinished = True; @@ -1016,8 +1003,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, int srcFinished, ECoderFinishMode finishMode, ECoderStatus *status) { - SizeT destLenOrig = *destLen; - SizeT srcLenOrig = *srcLen; + const SizeT destLenOrig = *destLen; + const SizeT srcLenOrig = *srcLen; *destLen = 0; *srcLen = 0; *status = CODER_STATUS_NOT_SPECIFIED; diff --git a/CPP/7zip/7zip.mak b/CPP/7zip/7zip.mak index 8bf7e73e..8e8cf246 100644 --- a/CPP/7zip/7zip.mak +++ b/CPP/7zip/7zip.mak @@ -231,7 +231,7 @@ $(C_OBJS): ../../../../C/$(*B).c {../../Compress}.cpp{$O}.obj:: $(COMPLB_O2) {../../Crypto}.cpp{$O}.obj:: - $(COMPLB_O2) + $(COMPLB_O2) -utf-8 {../../../../C}.c{$O}.obj:: $(CCOMPLB) diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak index a78c0fab..69dc1f69 100644 --- a/CPP/7zip/7zip_gcc.mak +++ b/CPP/7zip/7zip_gcc.mak @@ -827,16 +827,30 @@ $O/7zAes.o: ../../Crypto/7zAes.cpp $(CXX) $(CXXFLAGS) $< $O/7zAesRegister.o: ../../Crypto/7zAesRegister.cpp $(CXX) $(CXXFLAGS) $< +$O/7zKeyDerivation.o: ../../Crypto/7zKeyDerivation.cpp + $(CXX) $(CXXFLAGS) $< +$O/Ascon.o: ../../Crypto/Ascon.cpp + $(CXX) $(CXXFLAGS) $< +$O/Cascade.o: ../../Crypto/Cascade.cpp + $(CXX) $(CXXFLAGS) $< +$O/CascadeRegister.o: ../../Crypto/CascadeRegister.cpp + $(CXX) $(CXXFLAGS) $< +$O/HkdfBlake2sp.o: ../../Crypto/HkdfBlake2sp.cpp + $(CXX) $(CXXFLAGS) $< $O/HmacSha1.o: ../../Crypto/HmacSha1.cpp $(CXX) $(CXXFLAGS) $< $O/HmacSha256.o: ../../Crypto/HmacSha256.cpp $(CXX) $(CXXFLAGS) $< +$O/HmacSha512.o: ../../Crypto/HmacSha512.cpp + $(CXX) $(CXXFLAGS) $< $O/MyAes.o: ../../Crypto/MyAes.cpp $(CXX) $(CXXFLAGS) $< $O/MyAesReg.o: ../../Crypto/MyAesReg.cpp $(CXX) $(CXXFLAGS) $< $O/Pbkdf2HmacSha1.o: ../../Crypto/Pbkdf2HmacSha1.cpp $(CXX) $(CXXFLAGS) $< +$O/Pbkdf2HmacSha512.o: ../../Crypto/Pbkdf2HmacSha512.cpp + $(CXX) $(CXXFLAGS) $< $O/RandGen.o: ../../Crypto/RandGen.cpp $(CXX) $(CXXFLAGS) $< $O/Rar20Crypto.o: ../../Crypto/Rar20Crypto.cpp @@ -851,6 +865,14 @@ $O/ZipCrypto.o: ../../Crypto/ZipCrypto.cpp $(CXX) $(CXXFLAGS) $< $O/ZipStrong.o: ../../Crypto/ZipStrong.cpp $(CXX) $(CXXFLAGS) $< +$O/XChaCha20.o: ../../Crypto/XChaCha20.cpp + $(CXX) $(CXXFLAGS) $< +$O/XChaCha20Register.o: ../../Crypto/XChaCha20Register.cpp + $(CXX) $(CXXFLAGS) $< +$O/XChaCha20Poly1305.o: ../../Crypto/XChaCha20Poly1305.cpp + $(CXX) $(CXXFLAGS) $< +$O/XChaCha20Poly1305Register.o: ../../Crypto/XChaCha20Poly1305Register.cpp + $(CXX) $(CXXFLAGS) $< diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h index ecfee7cf..39a9e239 100644 --- a/CPP/7zip/Archive/7z/7zCompressionMode.h +++ b/CPP/7zip/Archive/7z/7zCompressionMode.h @@ -6,6 +6,8 @@ #include "../../Common/MethodId.h" #include "../../Common/MethodProps.h" +#include "7zHeader.h" + namespace NArchive { namespace N7z { @@ -64,6 +66,7 @@ struct CCompressionMethodMode UString Password; // _Wipe UInt64 MemoryUsageLimit; + CMethodId EncryptionMethodId; bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } CCompressionMethodMode(): @@ -78,6 +81,7 @@ struct CCompressionMethodMode , NumThreadGroups(0) #endif , MemoryUsageLimit((UInt64)1 << 30) + , EncryptionMethodId(k_AES) {} #ifdef Z7_CPP_IS_SUPPORTED_default diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp index 50cbff62..87af11c0 100644 --- a/CPP/7zip/Archive/7z/7zDecode.cpp +++ b/CPP/7zip/Archive/7z/7zDecode.cpp @@ -584,9 +584,29 @@ HRESULT CDecoder::Decode( progress2 = new CDecProgress(compressProgress); ISequentialOutStream *outStreamPointer = outStream; - return _mixer->Code(inStreamPointers, &outStreamPointer, + const HRESULT codeResult = _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress, dataAfterEnd_Error); + + if (codeResult == S_OK) + { + #ifndef Z7_NO_CRYPTO + for (i = 0; i < folderInfo.Coders.Size(); i++) + { + Z7_DECL_CMyComPtr_QI_FROM( + ICryptoAuthVerify, + authVerify, _mixer->GetCoder(i).GetUnknown()) + if (authVerify) + { + Int32 authResult = 0; + RINOK(authVerify->CryptoAuthVerify(&authResult)) + if (authResult != 0) + return S_FALSE; + } + } + #endif + } + return codeResult; } #ifdef USE_MIXER_ST @@ -596,4 +616,4 @@ HRESULT CDecoder::Decode( #endif } -}} +}} \ No newline at end of file diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp index 71d1ddb7..d4aa515b 100644 --- a/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/CPP/7zip/Archive/7z/7zEncode.cpp @@ -562,7 +562,7 @@ HRESULT CEncoder::EncoderConstr() throw 1; CMethodFull method; - method.Id = k_AES; + method.Id = _options.EncryptionMethodId; method.NumStreams = 1; _options.Methods.Add(method); @@ -687,7 +687,7 @@ HRESULT CEncoder::EncoderConstr() { CMethodFull method; method.NumStreams = 1; - method.Id = k_AES; + method.Id = _options.EncryptionMethodId; _options.Methods.Add(method); NCoderMixer2::CCoderStreamsInfo cod; diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp index 81dd9669..46c15c91 100644 --- a/CPP/7zip/Archive/7z/7zHandler.cpp +++ b/CPP/7zip/Archive/7z/7zHandler.cpp @@ -307,7 +307,7 @@ bool CHandler::IsFolderEncrypted(CNum folderIndex) const for (unsigned j = 0; j < idSize; j++) id64 = ((id64 << 8) | longID[j]); inByte.SkipDataNoCheck(idSize); - if (id64 == k_AES) + if (id64 == k_AES || id64 == k_XCHACHA20 || id64 == k_XCHACHA20_POLY1305 || id64 == k_AES_XCHACHA20_ASCON || id64 == k_AES_XCHACHA20_POLY1305) return true; if ((mainByte & 0x20) != 0) inByte.SkipDataNoCheck(inByte.ReadNum()); @@ -505,6 +505,46 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const ConvertUInt32ToString(numCyclesPower, s); } } + else if (id == k_XCHACHA20) + { + name = "XChaCha20"; + if (propsSize >= 1) + { + const Byte firstByte = props[0]; + const UInt32 numCyclesPower = firstByte & 0x3F; + ConvertUInt32ToString(numCyclesPower, s); + } + } + else if (id == k_XCHACHA20_POLY1305) + { + name = "XChaCha20-Poly1305"; + if (propsSize >= 1) + { + const Byte firstByte = props[0]; + const UInt32 numCyclesPower = firstByte & 0x3F; + ConvertUInt32ToString(numCyclesPower, s); + } + } + else if (id == k_AES_XCHACHA20_ASCON) + { + name = "AES+XChaCha20+Ascon"; + if (propsSize >= 1) + { + const Byte firstByte = props[0]; + const UInt32 numCyclesPower = firstByte & 0x3F; + ConvertUInt32ToString(numCyclesPower, s); + } + } + else if (id == k_AES_XCHACHA20_POLY1305) + { + name = "AES+XChaCha20-Poly1305"; + if (propsSize >= 1) + { + const Byte firstByte = props[0]; + const UInt32 numCyclesPower = firstByte & 0x3F; + ConvertUInt32ToString(numCyclesPower, s); + } + } } if (name) diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h index ed535f74..76a1e366 100644 --- a/CPP/7zip/Archive/7z/7zHandler.h +++ b/CPP/7zip/Archive/7z/7zHandler.h @@ -60,6 +60,7 @@ class COutHandler: public CMultiMethodProps UInt32 _decoderCompatibilityVersion; CUIntVector _enabledFilters; CUIntVector _disabledFilters; + CMethodId _encryptionMethodId; void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp index c1c2b636..b2cd3af7 100644 --- a/CPP/7zip/Archive/7z/7zHandlerOut.cpp +++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp @@ -749,6 +749,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt if (methodMode.PasswordIsDefined) { + methodMode.EncryptionMethodId = _encryptionMethodId; if (_encryptHeadersSpecified) encryptHeaders = _encryptHeaders; #ifndef Z7_NO_CRYPTO @@ -760,6 +761,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt { headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined; headerMethod.Password = methodMode.Password; + headerMethod.EncryptionMethodId = _encryptionMethodId; } } @@ -874,6 +876,7 @@ void COutHandler::InitProps7z() _decoderCompatibilityVersion = k_decoderCompatibilityVersion; _enabledFilters.Clear(); _disabledFilters.Clear(); + _encryptionMethodId = k_AES; } void COutHandler::InitProps() @@ -1023,6 +1026,29 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val return S_OK; } + if (name.IsEqualTo("em")) + { + if (value.vt != VT_BSTR) + return E_INVALIDARG; + UString m = value.bstrVal; + m.RemoveChar(L'-'); + m.RemoveChar(L'+'); + m.MakeLower_Ascii(); + if (m.IsEqualTo("aes256")) + _encryptionMethodId = k_AES; + else if (m.IsEqualTo("xchacha20")) + _encryptionMethodId = k_XCHACHA20; + else if (m.IsEqualTo("xchacha20poly1305")) + _encryptionMethodId = k_XCHACHA20_POLY1305; + else if (m.IsEqualTo("axa") || m.IsEqualTo("aesxchacha20ascon")) + _encryptionMethodId = k_AES_XCHACHA20_ASCON; + else if (m.IsEqualTo("axp") || m.IsEqualTo("aesxchacha20poly1305")) + _encryptionMethodId = k_AES_XCHACHA20_POLY1305; + else + return E_INVALIDARG; + return S_OK; + } + { bool processed; RINOK(TimeOptions.Parse(name, value, processed)) diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h index 22e79607..9fe4f557 100644 --- a/CPP/7zip/Archive/7z/7zHeader.h +++ b/CPP/7zip/Archive/7z/7zHeader.h @@ -122,7 +122,11 @@ const UInt32 k_ARM = 0x3030501; const UInt32 k_ARMT = 0x3030701; const UInt32 k_SPARC = 0x3030805; -const UInt32 k_AES = 0x6F10701; +const UInt32 k_AES = 0x6F10701; +const UInt32 k_XCHACHA20 = 0x6F10702; +const UInt32 k_XCHACHA20_POLY1305 = 0x6F10703; +const UInt32 k_AES_XCHACHA20_POLY1305 = 0x6F10704; +const UInt32 k_AES_XCHACHA20_ASCON = 0x6F10705; // const UInt32 k_ZSTD = 0x4015D; // winzip zstd // 0x4F71101, 7z-zstd diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp index e2efc520..eb39478f 100644 --- a/CPP/7zip/Archive/7z/7zIn.cpp +++ b/CPP/7zip/Archive/7z/7zIn.cpp @@ -698,22 +698,24 @@ void CInArchive::ReadPackInfo(CFolders &f) WaitId(NID::kSize); f.PackPositions.Alloc(numPackStreams + 1); + UInt64 * const packPositions = f.PackPositions; f.NumPackStreams = numPackStreams; UInt64 sum = 0; - for (CNum i = 0; i < numPackStreams; i++) + for (CNum i = 0;;) { - f.PackPositions[i] = sum; + packPositions[i] = sum; + if (i == numPackStreams) + break; + i++; const UInt64 packSize = ReadNumber(); sum += packSize; if (sum < packSize) ThrowIncorrect(); } - f.PackPositions[numPackStreams] = sum; - UInt64 type; for (;;) { - type = ReadID(); + const UInt64 type = ReadID(); if (type == NID::kEnd) return; if (type == NID::kCRC) @@ -857,19 +859,20 @@ void CInArchive::ReadUnpackInfo( StreamUsed[index] = true; } - for (i = 0; i < numCoders; i++) + for (i = 0;;) + { if (!CoderUsed[i]) - { - indexOfMainStream = i; break; - } - - if (i == numCoders) - ThrowUnsupported(); + if (++i == numCoders) + ThrowUnsupported(); + } + indexOfMainStream = i; } folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; numCodersOutStreams += numCoders; + if (numCodersOutStreams < numCoders) + ThrowUnsupported(); folders.FoStartPackStreamIndex[fo] = packStreamIndex; if (numPackStreams > folders.NumPackStreams - packStreamIndex) ThrowIncorrect(); @@ -880,7 +883,7 @@ void CInArchive::ReadUnpackInfo( const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr); folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams; folders.FoStartPackStreamIndex[fo] = packStreamIndex; - folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr); + folders.FoCodersDataOffset[fo] = dataSize; folders.CodersData.CopyFrom(startBufPtr, dataSize); // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported(); @@ -898,6 +901,8 @@ void CInArchive::ReadUnpackInfo( return; if (type == NID::kCRC) { + if (!folders.FolderCRCs.Defs.IsEmpty()) + ThrowIncorrect(); ReadHashDigests(numFolders, folders.FolderCRCs); continue; } @@ -911,19 +916,35 @@ void CInArchive::ReadSubStreamsInfo( CUInt32DefVector &digests) { folders.NumUnpackStreamsVector.Alloc(folders.NumFolders); - CNum i; - for (i = 0; i < folders.NumFolders; i++) - folders.NumUnpackStreamsVector[i] = 1; + bool NumUnpackStream_isFilled = false; UInt64 type; + + CNum numUnpackStreams = folders.NumFolders; for (;;) { type = ReadID(); if (type == NID::kNumUnpackStream) { - for (i = 0; i < folders.NumFolders; i++) - folders.NumUnpackStreamsVector[i] = ReadNum(); + if (NumUnpackStream_isFilled) + ThrowIncorrect(); + NumUnpackStream_isFilled = true; + CNum numFolders = folders.NumFolders; + numUnpackStreams = 0; + if (numFolders) + { + UInt32 *dest = folders.NumUnpackStreamsVector.NonConstData(); + do + { + const CNum num = ReadNum(); + *dest++ = num; + numUnpackStreams += num; + if (numUnpackStreams < num) + ThrowUnsupported(); + } + while (--numFolders); + } continue; } if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd) @@ -931,6 +952,20 @@ void CInArchive::ReadSubStreamsInfo( SkipData(); } + if (!NumUnpackStream_isFilled) + { + CNum numFolders = folders.NumFolders; + if (numFolders) + { + UInt32 *dest = folders.NumUnpackStreamsVector.NonConstData(); + do + *dest++ = 1; + while (--numFolders); + } + } + + unpackSizes.ClearAndReserve(numUnpackStreams); + CNum i; if (type == NID::kSize) { for (i = 0; i < folders.NumFolders; i++) @@ -943,16 +978,20 @@ void CInArchive::ReadSubStreamsInfo( UInt64 sum = 0; for (CNum j = 1; j < numSubstreams; j++) { + if (unpackSizes.Size() >= numUnpackStreams) + ThrowIncorrect(); // internal failure const UInt64 size = ReadNumber(); - unpackSizes.Add(size); + unpackSizes.AddInReserved(size); sum += size; if (sum < size) ThrowIncorrect(); } + if (unpackSizes.Size() >= numUnpackStreams) + ThrowIncorrect(); // internal failure const UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i); if (folderUnpackSize < sum) ThrowIncorrect(); - unpackSizes.Add(folderUnpackSize - sum); + unpackSizes.AddInReserved(folderUnpackSize - sum); } type = ReadID(); } @@ -966,10 +1005,17 @@ void CInArchive::ReadSubStreamsInfo( if (val > 1) ThrowIncorrect(); if (val == 1) - unpackSizes.Add(folders.GetFolderUnpackSize(i)); + { + if (unpackSizes.Size() >= numUnpackStreams) + ThrowIncorrect(); // internal failure + unpackSizes.AddInReserved(folders.GetFolderUnpackSize(i)); + } } } + if (unpackSizes.Size() != numUnpackStreams) + ThrowIncorrect(); + unsigned numDigests = 0; for (i = 0; i < folders.NumFolders; i++) { @@ -984,6 +1030,8 @@ void CInArchive::ReadSubStreamsInfo( break; if (type == NID::kCRC) { + if (!digests.Defs.IsEmpty()) + ThrowIncorrect(); // CUInt32DefVector digests2; // ReadHashDigests(numDigests, digests2); CBoolVector digests2; @@ -1092,10 +1140,13 @@ void CInArchive::ReadStreamsInfo( So we don't need to fill digests with values. */ // digests.Vals.ClearAndSetSize(folders.NumFolders); // BoolVector_Fill_False(digests.Defs, folders.NumFolders); + unpackSizes.ClearAndSetSize(folders.NumFolders); + UInt64 * const unpackSizes2 = unpackSizes.NonConstData(); + CNum * const numUnpackStreamsVector2 = folders.NumUnpackStreamsVector; for (CNum i = 0; i < folders.NumFolders; i++) { - folders.NumUnpackStreamsVector[i] = 1; - unpackSizes.Add(folders.GetFolderUnpackSize(i)); + numUnpackStreamsVector2[i] = 1; + unpackSizes2[i] = folders.GetFolderUnpackSize(i); // digests.Vals[i] = 0; } } @@ -1648,8 +1699,8 @@ HRESULT CInArchive::ReadDatabase2( db.PhySize = kHeaderSize; db.IsArc = false; - if ((Int64)nextHeaderOffset < 0 || - nextHeaderSize > ((UInt64)1 << 62)) + if (nextHeaderOffset >= (UInt64)1 << 62 || + nextHeaderSize > ((UInt64)1 << 48)) return S_FALSE; HeadersSize = kHeaderSize; diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h index 06737c81..8e785195 100644 --- a/CPP/7zip/Archive/7z/7zItem.h +++ b/CPP/7zip/Archive/7z/7zItem.h @@ -83,8 +83,11 @@ struct CFolder bool IsEncrypted() const { FOR_VECTOR(i, Coders) - if (Coders[i].MethodID == k_AES) + { + CMethodId id = Coders[i].MethodID; + if (id == k_AES || id == k_XCHACHA20 || id == k_XCHACHA20_POLY1305 || id == k_AES_XCHACHA20_ASCON || id == k_AES_XCHACHA20_POLY1305) return true; + } return false; } }; diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp index d0c8cf29..dfedd909 100644 --- a/CPP/7zip/Archive/7z/7zOut.cpp +++ b/CPP/7zip/Archive/7z/7zOut.cpp @@ -933,6 +933,7 @@ HRESULT COutArchive::WriteDatabase( CCompressionMethodMode encryptOptions; encryptOptions.PasswordIsDefined = options->PasswordIsDefined; encryptOptions.Password = options->Password; + encryptOptions.EncryptionMethodId = options->EncryptionMethodId; CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions); CRecordVector packSizes; CObjectVector folders; diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index 6ba04a24..b05d3cf7 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp @@ -36,13 +36,6 @@ struct CFilterMode UInt32 Offset; // for k_ARM64 / k_RISCV // UInt32 AlignSizeOpt; // for k_ARM64 - CFilterMode(): - Id(0), - Delta(0), - Offset(0) - // , AlignSizeOpt(0) - {} - void ClearFilterMode() { Id = 0; @@ -437,7 +430,11 @@ struct CFilterMode2: public CFilterMode bool Encrypted; unsigned GroupIndex; - CFilterMode2(): Encrypted(false) {} + void Construct() + { + ClearFilterMode(); + Encrypted = false; + } int Compare(const CFilterMode2 &m) const { @@ -546,6 +543,7 @@ static unsigned Get_FilterGroup_for_Folder( CRecordVector &filters, const CFolderEx &f, bool extractFilter) { CFilterMode2 m; + m.Construct(); // m.Id = 0; // m.Delta = 0; // m.Offset = 0; @@ -795,14 +793,14 @@ struct CRefItem unsigned NamePos; unsigned ExtensionIndex; - CRefItem() {} - CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType): - UpdateItem(&ui), - Index(index), - ExtensionPos(0), - NamePos(0), - ExtensionIndex(0) + void Construct(UInt32 index, const CUpdateItem &ui, bool sortByType) { + UpdateItem = &ui; + Index = index; + ExtensionPos = 0; + NamePos = 0; + ExtensionIndex = 0; + if (sortByType) { const int slashPos = ui.Name.ReverseFind_PathSepar(); @@ -2154,6 +2152,7 @@ HRESULT Update( continue; CFilterMode2 fm; + fm.Construct(); if (useFilters) { // analysis.ATime_Defined = false; @@ -2710,7 +2709,7 @@ HRESULT Update( unsigned i; for (i = 0; i < numFiles; i++) - refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType); + refItems[i].Construct(group.Indices[i], updateItems[group.Indices[i]], sortByType); CSortParam sortParam; // sortParam.TreeFolders = &treeFolders; diff --git a/CPP/7zip/Archive/ApfsHandler.cpp b/CPP/7zip/Archive/ApfsHandler.cpp index 62b00ed5..28769918 100644 --- a/CPP/7zip/Archive/ApfsHandler.cpp +++ b/CPP/7zip/Archive/ApfsHandler.cpp @@ -3487,7 +3487,7 @@ static const CStatProp kProps[] = { NULL, kpidChangeTime, VT_FILETIME }, { "Added Time", kpidAddTime, VT_FILETIME }, { NULL, kpidMethod, VT_BSTR }, - { NULL, kpidINode, VT_UI8 }, + { NULL, kpidINode, VT_UI4 }, { NULL, kpidLinks, VT_UI4 }, { NULL, kpidSymLink, VT_BSTR }, { NULL, kpidUserId, VT_UI4 }, @@ -3496,7 +3496,7 @@ static const CStatProp kProps[] = #ifdef APFS_SHOW_ALT_STREAMS { NULL, kpidIsAltStream, VT_BOOL }, #endif - { "Parent iNode", kpidParentINode, VT_UI8 }, + { "Parent iNode", kpidParentINode, VT_UI4 }, { "Primary Name", kpidPrimeName, VT_BSTR }, { "Generation", kpidGeneration, VT_UI4 }, { "Written Size", kpidBytesWritten, VT_UI8 }, diff --git a/CPP/7zip/Archive/ExtHandler.cpp b/CPP/7zip/Archive/ExtHandler.cpp index 5af2a929..d3793735 100644 --- a/CPP/7zip/Archive/ExtHandler.cpp +++ b/CPP/7zip/Archive/ExtHandler.cpp @@ -628,6 +628,8 @@ struct CNode UInt32 Gid; // fixed 21.02 // UInt16 Checksum; + UInt32 NumLinksCalced; + UInt64 FileSize; CExtTime MTime; CExtTime ATime; @@ -639,17 +641,16 @@ struct CNode UInt32 NumLinks; UInt32 Flags; - UInt32 NumLinksCalced; - Byte Block[kNodeBlockFieldSize]; - CNode(): - ParentNode(-1), - ItemIndex(-1), - SymLinkIndex(-1), - DirIndex(-1), - NumLinksCalced(0) - {} + void Construct() + { + ParentNode = -1; + ItemIndex = -1; + SymLinkIndex = -1; + DirIndex = -1; + NumLinksCalced = 0; + } bool IsFlags_HUGE() const { return (Flags & k_NodeFlags_HUGE) != 0; } bool IsFlags_EXTENTS() const { return (Flags & k_NodeFlags_EXTENTS) != 0; } @@ -1172,21 +1173,19 @@ HRESULT CHandler::Open2(IInStream *inStream) { // ---------- Read groups ---------- - CByteBuffer gdBuf; const size_t gdBufSize = (size_t)numGroups << gdBits; if ((gdBufSize >> gdBits) != numGroups) return S_FALSE; + CByteBuffer gdBuf; gdBuf.Alloc(gdBufSize); RINOK(SeekAndRead(inStream, (_h.BlockBits <= 10 ? 2 : 1), gdBuf, gdBufSize)) - for (unsigned i = 0; i < numGroups; i++) + const unsigned gd_Size = (unsigned)1 << gdBits; + const Byte *p = gdBuf; + for (unsigned i = 0; i < numGroups; i++, p += gd_Size) { CGroupDescriptor gd; - - const Byte *p = gdBuf + ((size_t)i << gdBits); - const unsigned gd_Size = (unsigned)1 << gdBits; gd.Parse(p, gd_Size); - if (_h.UseMetadataChecksum()) { // use CRC32c @@ -1228,7 +1227,10 @@ HRESULT CHandler::Open2(IInStream *inStream) if (numNodes > (1 << 24)) return S_FALSE; } - + + const size_t blockSize = (size_t)1 << _h.BlockBits; + if (numNodes > blockSize * 8) + return S_FALSE; const UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1; // numReserveInodes = _h.NumInodes + 1; if (numReserveInodes != 0) @@ -1241,7 +1243,6 @@ HRESULT CHandler::Open2(IInStream *inStream) nodesData.Alloc(nodesDataSize); CByteBuffer nodesMap; - const size_t blockSize = (size_t)1 << _h.BlockBits; nodesMap.Alloc(blockSize); unsigned globalNodeIndex = 0; @@ -1282,6 +1283,7 @@ HRESULT CHandler::Open2(IInStream *inStream) } CNode node; + node.Construct(); PRF(printf("\nnode = %5d ", (unsigned)n)); diff --git a/CPP/7zip/Archive/HfsHandler.cpp b/CPP/7zip/Archive/HfsHandler.cpp index 46e02397..5df00ede 100644 --- a/CPP/7zip/Archive/HfsHandler.cpp +++ b/CPP/7zip/Archive/HfsHandler.cpp @@ -437,7 +437,7 @@ struct CRef int AttrIndex; int Parent; - CRef(): AttrIndex(kAttrIndex_Item), Parent(-1) {} + void Construct() { AttrIndex = kAttrIndex_Item; Parent = -1; } bool IsResource() const { return AttrIndex == kAttrIndex_Resource; } bool IsAltStream() const { return AttrIndex != kAttrIndex_Item; } bool IsItem() const { return AttrIndex == kAttrIndex_Item; } @@ -1259,6 +1259,7 @@ HRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector= _items.Size()) @@ -1070,6 +1068,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } else { + const CItem &item = _items[index]; switch (propID) { case kpidPath: diff --git a/CPP/7zip/Archive/MbrHandler.cpp b/CPP/7zip/Archive/MbrHandler.cpp index 82d34fd6..53663e8e 100644 --- a/CPP/7zip/Archive/MbrHandler.cpp +++ b/CPP/7zip/Archive/MbrHandler.cpp @@ -53,7 +53,12 @@ struct CChs SectCyl = p[1]; Cyl8 = p[2]; } - bool Check() const { return GetSector() > 0; } + bool Check() const + { + if ((Head | SectCyl | Cyl8) == 0) + return true; + return GetSector() > 0; + } }; diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp index 194e5bf1..577062ef 100644 --- a/CPP/7zip/Archive/Nsis/NsisIn.cpp +++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp @@ -190,7 +190,7 @@ static const CCommandInfo k_Commands[kNumCmds] = { 2 }, // "SetFileAttributes" }, { 3 }, // CreateDirectory, SetOutPath { 3 }, // "IfFileExists" }, - { 3 }, // SetRebootFlag, ... + { 4 }, // SetRebootFlag, ... { 4 }, // "If" }, // IfAbort, IfSilent, IfErrors, IfRebootFlag { 2 }, // "Get" }, // GetInstDirError, GetErrorLevel { 4 }, // "Rename" }, @@ -3910,6 +3910,10 @@ HRESULT CInArchive::ReadEntries(const CBlockHeader &bh) if (params[2] != 0) { s += " lastused"; + // (params[3] == (UInt32)(Int32)-1) is possible in NSIS 3.10. + // SetDetailsPrint lastused (special) + if ((Int32)params[3] < 0) + s += " ; (special)"; break; } UInt32 v; diff --git a/CPP/7zip/Archive/NtfsHandler.cpp b/CPP/7zip/Archive/NtfsHandler.cpp index d26612b3..006f0ad1 100644 --- a/CPP/7zip/Archive/NtfsHandler.cpp +++ b/CPP/7zip/Archive/NtfsHandler.cpp @@ -1433,7 +1433,12 @@ struct CItem int ParentHost; /* index in Items array, if it's AltStream -1: if it's not AltStream */ - CItem(): DataIndex(k_Item_DataIndex_IsDir), ParentFolder(-1), ParentHost(-1) {} + void Construct() + { + DataIndex = k_Item_DataIndex_IsDir; + ParentFolder = -1; + ParentHost = -1; + } bool IsAltStream() const { return ParentHost != -1; } bool IsDir() const { return DataIndex == k_Item_DataIndex_IsDir; } @@ -2060,6 +2065,7 @@ HRESULT CDatabase::Open() } CItem item; + item.Construct(); item.NameIndex = t; item.RecIndex = i; item.DataIndex = rec.IsDir() ? diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp index 79f89ef9..f5f66b02 100644 --- a/CPP/7zip/Archive/PeHandler.cpp +++ b/CPP/7zip/Archive/PeHandler.cpp @@ -758,7 +758,13 @@ struct CMixItem int StringIndex; int VersionIndex; - CMixItem(): SectionIndex(-1), ResourceIndex(-1), StringIndex(-1), VersionIndex(-1) {} + void Construct() + { + SectionIndex = -1; + ResourceIndex = -1; + StringIndex = -1; + VersionIndex = -1; + } bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; } }; @@ -820,20 +826,22 @@ Z7_CLASS_IMP_CHandler_IInArchive_2( CObjectVector _versionKeys; CByteBuffer _buf; + bool _oneLang; - UString _resourcesPrefix; - CUsedBitmap _usedRes; // bool _parseResources; bool _checksumError; bool _sectionsError; + bool _coffMode; + bool _allowTail; + + UString _resourcesPrefix; + CUsedBitmap _usedRes; + bool IsOpt() const { return _header.OptHeaderSize != 0; } COptHeader _optHeader; - bool _coffMode; - bool _allowTail; - HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection); HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback); @@ -2269,6 +2277,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi if (ParseVersion((const Byte *)_buf + offset, item.Size, f, _versionKeys)) { CMixItem mixItem; + mixItem.Construct(); mixItem.VersionIndex = (int)_versionFiles.Size(); mixItem.SectionIndex = (int)sectionIndex; // check it !!!! CByteBuffer_WithLang &vf = _versionFiles.AddNew(); @@ -2300,6 +2309,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi if (_strings[i].FinalSize() == 0) continue; CMixItem mixItem; + mixItem.Construct(); mixItem.StringIndex = (int)i; mixItem.SectionIndex = (int)sectionIndex; _mixItems.Add(mixItem); @@ -2654,6 +2664,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) if (item.Enabled) { CMixItem mixItem; + mixItem.Construct(); mixItem.SectionIndex = (int)i; mixItem.ResourceIndex = (int)j; if (item.IsRcDataOrUnknown()) @@ -2717,6 +2728,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback) } CMixItem mixItem; + mixItem.Construct(); mixItem.SectionIndex = (int)i; _mixItems.Add(mixItem); } diff --git a/CPP/7zip/Archive/SparseHandler.cpp b/CPP/7zip/Archive/SparseHandler.cpp index 5e666ed7..70bcb6fc 100644 --- a/CPP/7zip/Archive/SparseHandler.cpp +++ b/CPP/7zip/Archive/SparseHandler.cpp @@ -78,7 +78,7 @@ struct CChunk Byte Fill [kFillSize]; UInt64 PhyOffset; - CChunk() + void Construct() { Fill[0] = Fill[1] = @@ -293,6 +293,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) if (size < kChunkHeaderSize) return S_FALSE; CChunk c; + c.Construct(); c.PhyOffset = offset + kChunkHeaderSize; c.VirtBlock = virtBlock; offset += size; @@ -364,6 +365,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) { CChunk c; + c.Construct(); c.VirtBlock = virtBlock; c.PhyOffset = offset; Chunks.AddInReserved(c); diff --git a/CPP/7zip/Archive/SquashfsHandler.cpp b/CPP/7zip/Archive/SquashfsHandler.cpp index b66be042..83cb1cfd 100644 --- a/CPP/7zip/Archive/SquashfsHandler.cpp +++ b/CPP/7zip/Archive/SquashfsHandler.cpp @@ -812,7 +812,7 @@ struct CItem int Parent; UInt32 Ptr; - CItem(): Node(-1), Parent(-1), Ptr(0) {} + void Construct() { Node = -1; Parent = -1; Ptr = 0; } }; struct CData @@ -1497,7 +1497,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned if (rem == 0) return S_FALSE; - UInt32 nameOffset = _h.GetFileNameOffset(); + const UInt32 nameOffset = _h.GetFileNameOffset(); if (rem < nameOffset) return S_FALSE; @@ -1505,7 +1505,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned return S_FALSE; if (_openCallback) { - UInt64 numFiles = _items.Size(); + const UInt64 numFiles = _items.Size(); if ((numFiles & 0xFFFF) == 0) { RINOK(_openCallback->SetCompleted(&numFiles, NULL)) @@ -1513,6 +1513,7 @@ HRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned } CItem item; + item.Construct(); item.Ptr = (UInt32)(p - (const Byte *)_dirs.Data); UInt32 size; diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp index 3b2cb316..0fd7d239 100644 --- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp +++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp @@ -177,7 +177,12 @@ struct CUpdateItem int InArcIndex; // >= 0, if we use OLD Data // -1, if we use NEW Data - CUpdateItem(): MetaIndex(-1), AltStreamIndex(-1), InArcIndex(-1) {} + void Construct() + { + MetaIndex = -1; + AltStreamIndex = -1; + InArcIndex = -1; + } }; @@ -894,6 +899,7 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu for (i = 0; i < numItems; i++) { CUpdateItem ui; + ui.Construct(); UInt32 indexInArchive; Int32 newData, newProps; RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive)) diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp index b2236dd9..33fbe821 100644 --- a/CPP/7zip/Archive/Wim/WimIn.cpp +++ b/CPP/7zip/Archive/Wim/WimIn.cpp @@ -609,6 +609,7 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent, unsigned dirLevel) return S_FALSE; CItem item; + item.Construct(); const UInt32 attrib = Get32(p + 8); item.IsDir = ((attrib & 0x10) != 0); { @@ -729,6 +730,7 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent, unsigned dirLevel) { ThereAreAltStreams = true; CItem item2; + item2.Construct(); item2.Offset = pos; item2.IsAltStream = true; item2.Parent = (int)prevIndex; @@ -1531,6 +1533,7 @@ HRESULT CDatabase::FillAndCheck(const CObjectVector &volumes) if (!r.IsSolidBig() || Solids[r.SolidIndex].FirstSmallStream < 0) { CItem item; + item.Construct(); item.Offset = 0; item.StreamIndex = (int)i; item.ImageIndex = -1; diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h index 571f4144..ae7cd6b6 100644 --- a/CPP/7zip/Archive/Wim/WimIn.h +++ b/CPP/7zip/Archive/Wim/WimIn.h @@ -347,15 +347,16 @@ struct CItem bool HasMetadata() const { return ImageIndex >= 0; } - CItem(): - IndexInSorted(-1), - StreamIndex(-1), - Parent(-1), - IsDir(false), - IsAltStream(false), - DirLevel(0), - SubDirOffset(0) - {} + void Construct() + { + IndexInSorted = -1; + StreamIndex = -1; + Parent = -1; + IsDir = false; + IsAltStream = false; + DirLevel = 0; + SubDirOffset = 0; + } }; struct CImage diff --git a/CPP/7zip/Bundles/Alone/Alone.dsp b/CPP/7zip/Bundles/Alone/Alone.dsp index 6512e409..bc7bede1 100644 --- a/CPP/7zip/Bundles/Alone/Alone.dsp +++ b/CPP/7zip/Bundles/Alone/Alone.dsp @@ -1941,6 +1941,14 @@ SOURCE=..\..\Crypto\7zAesRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Crypto\7zKeyDerivation.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zKeyDerivation.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\HmacSha1.cpp !IF "$(CFG)" == "Alone - Win32 Release" @@ -1963,6 +1971,28 @@ SOURCE=..\..\Crypto\HmacSha1.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\HmacSha512.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha512.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\MyAes.cpp !IF "$(CFG)" == "Alone - Win32 Release" @@ -2014,6 +2044,31 @@ SOURCE=..\..\Crypto\Pbkdf2HmacSha1.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.cpp + +!IF "$(CFG)" == "Alone - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 Debug" + +!ELSEIF "$(CFG)" == "Alone - Win32 ReleaseU" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Alone - Win32 DebugU" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\RandGen.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Alone/makefile b/CPP/7zip/Bundles/Alone/makefile index 9f81f9e3..a7f8c016 100644 --- a/CPP/7zip/Bundles/Alone/makefile +++ b/CPP/7zip/Bundles/Alone/makefile @@ -186,12 +186,24 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ + $O\7zKeyDerivation.obj \ + $O\Ascon.obj \ + $O\Cascade.obj \ + $O\CascadeRegister.obj \ + $O\HkdfBlake2sp.obj \ $O\HmacSha1.obj \ + $O\HmacSha256.obj \ + $O\HmacSha512.obj \ $O\MyAes.obj \ $O\MyAesReg.obj \ $O\Pbkdf2HmacSha1.obj \ + $O\Pbkdf2HmacSha512.obj \ $O\RandGen.obj \ $O\WzAes.obj \ + $O\XChaCha20.obj \ + $O\XChaCha20Register.obj \ + $O\XChaCha20Poly1305.obj \ + $O\XChaCha20Poly1305Register.obj \ $O\ZipCrypto.obj \ $O\ZipStrong.obj \ @@ -200,6 +212,7 @@ C_OBJS = \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bcj2Enc.obj \ + $O\Blake2s.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ @@ -240,6 +253,7 @@ C_OBJS = \ !include "../../LzmaDec.mak" !include "../../Sha1.mak" !include "../../Sha256.mak" +!include "../../Sha512.mak" !include "../../Sort.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Alone/makefile.gcc b/CPP/7zip/Bundles/Alone/makefile.gcc index 822d2526..5e8ab3f4 100644 --- a/CPP/7zip/Bundles/Alone/makefile.gcc +++ b/CPP/7zip/Bundles/Alone/makefile.gcc @@ -128,6 +128,8 @@ COMMON_OBJS = \ $O/Sha1Reg.o \ $O/Sha256Prepare.o \ $O/Sha256Reg.o \ + $O/Sha512Prepare.o \ + $O/Sha512Reg.o \ $O/StdInStream.o \ $O/StdOutStream.o \ $O/StringConvert.o \ @@ -277,12 +279,24 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O/7zAes.o \ $O/7zAesRegister.o \ + $O/7zKeyDerivation.o \ + $O/Ascon.o \ + $O/Cascade.o \ + $O/CascadeRegister.o \ + $O/HkdfBlake2sp.o \ $O/HmacSha1.o \ + $O/HmacSha256.o \ + $O/HmacSha512.o \ $O/MyAes.o \ $O/MyAesReg.o \ $O/Pbkdf2HmacSha1.o \ + $O/Pbkdf2HmacSha512.o \ $O/RandGen.o \ $O/WzAes.o \ + $O/XChaCha20.o \ + $O/XChaCha20Register.o \ + $O/XChaCha20Poly1305.o \ + $O/XChaCha20Poly1305Register.o \ $O/ZipCrypto.o \ $O/ZipStrong.o \ @@ -295,6 +309,7 @@ C_OBJS = \ $O/Alloc.o \ $O/Bcj2.o \ $O/Bcj2Enc.o \ + $O/Blake2s.o \ $O/Bra.o \ $O/Bra86.o \ $O/BraIA64.o \ @@ -320,6 +335,8 @@ C_OBJS = \ $O/Sha1Opt.o \ $O/Sha256.o \ $O/Sha256Opt.o \ + $O/Sha512.o \ + $O/Sha512Opt.o \ $O/Sort.o \ $O/SwapBytes.o \ $O/Xxh64.o \ diff --git a/CPP/7zip/Bundles/Alone7z/Alone.dsp b/CPP/7zip/Bundles/Alone7z/Alone.dsp index c5c149fd..755bb485 100644 --- a/CPP/7zip/Bundles/Alone7z/Alone.dsp +++ b/CPP/7zip/Bundles/Alone7z/Alone.dsp @@ -2067,6 +2067,30 @@ SOURCE=..\..\Crypto\7zAesRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Crypto\7zKeyDerivation.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zKeyDerivation.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha512.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha512.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\MyAes.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/Alone7z/makefile b/CPP/7zip/Bundles/Alone7z/makefile index f0a813ac..ea3702cf 100644 --- a/CPP/7zip/Bundles/Alone7z/makefile +++ b/CPP/7zip/Bundles/Alone7z/makefile @@ -125,15 +125,28 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ + $O\7zKeyDerivation.obj \ + $O\Ascon.obj \ + $O\Cascade.obj \ + $O\CascadeRegister.obj \ + $O\HkdfBlake2sp.obj \ + $O\HmacSha256.obj \ + $O\HmacSha512.obj \ $O\MyAes.obj \ $O\MyAesReg.obj \ + $O\Pbkdf2HmacSha512.obj \ $O\RandGen.obj \ + $O\XChaCha20.obj \ + $O\XChaCha20Register.obj \ + $O\XChaCha20Poly1305.obj \ + $O\XChaCha20Poly1305Register.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bcj2Enc.obj \ + $O\Blake2s.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ @@ -163,6 +176,7 @@ C_OBJS = \ !include "../../LzFindOpt.mak" !include "../../LzmaDec.mak" !include "../../Sha256.mak" +!include "../../Sha512.mak" !include "../../Sort.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Alone7z/makefile.gcc b/CPP/7zip/Bundles/Alone7z/makefile.gcc index 179bfef5..a37e5467 100644 --- a/CPP/7zip/Bundles/Alone7z/makefile.gcc +++ b/CPP/7zip/Bundles/Alone7z/makefile.gcc @@ -124,6 +124,8 @@ COMMON_OBJS = \ $O/NewHandler.o \ $O/Sha256Prepare.o \ $O/Sha256Reg.o \ + $O/Sha512Prepare.o \ + $O/Sha512Reg.o \ $O/StdInStream.o \ $O/StdOutStream.o \ $O/StringConvert.o \ @@ -220,9 +222,21 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O/7zAes.o \ $O/7zAesRegister.o \ + $O/7zKeyDerivation.o \ + $O/Ascon.o \ + $O/Cascade.o \ + $O/CascadeRegister.o \ + $O/HkdfBlake2sp.o \ + $O/HmacSha256.o \ + $O/HmacSha512.o \ $O/MyAes.o \ $O/MyAesReg.o \ + $O/Pbkdf2HmacSha512.o \ $O/RandGen.o \ + $O/XChaCha20.o \ + $O/XChaCha20Register.o \ + $O/XChaCha20Poly1305.o \ + $O/XChaCha20Poly1305Register.o \ C_OBJS = \ $O/7zCrc.o \ @@ -233,6 +247,7 @@ C_OBJS = \ $O/Alloc.o \ $O/Bcj2.o \ $O/Bcj2Enc.o \ + $O/Blake2s.o \ $O/Bra.o \ $O/Bra86.o \ $O/BraIA64.o \ @@ -248,6 +263,8 @@ C_OBJS = \ $O/MtDec.o \ $O/Sha256.o \ $O/Sha256Opt.o \ + $O/Sha512.o \ + $O/Sha512Opt.o \ $O/SwapBytes.o \ $O/Xz.o \ $O/XzDec.o \ diff --git a/CPP/7zip/Bundles/Format7z/makefile b/CPP/7zip/Bundles/Format7z/makefile index 3d4754ca..5c823590 100644 --- a/CPP/7zip/Bundles/Format7z/makefile +++ b/CPP/7zip/Bundles/Format7z/makefile @@ -107,15 +107,28 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ + $O\7zKeyDerivation.obj \ + $O\Ascon.obj \ + $O\Cascade.obj \ + $O\CascadeRegister.obj \ + $O\HkdfBlake2sp.obj \ + $O\HmacSha256.obj \ + $O\HmacSha512.obj \ $O\MyAes.obj \ $O\MyAesReg.obj \ + $O\Pbkdf2HmacSha512.obj \ $O\RandGen.obj \ + $O\XChaCha20.obj \ + $O\XChaCha20Register.obj \ + $O\XChaCha20Poly1305.obj \ + $O\XChaCha20Poly1305Register.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ $O\Bcj2Enc.obj \ + $O\Blake2s.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ @@ -143,6 +156,7 @@ C_OBJS = \ !include "../../LzFindOpt.mak" !include "../../LzmaDec.mak" !include "../../Sha256.mak" +!include "../../Sha512.mak" !include "../../Sort.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Format7zExtract/makefile b/CPP/7zip/Bundles/Format7zExtract/makefile index 4e2ed3e8..b26631a5 100644 --- a/CPP/7zip/Bundles/Format7zExtract/makefile +++ b/CPP/7zip/Bundles/Format7zExtract/makefile @@ -87,13 +87,26 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ + $O\7zKeyDerivation.obj \ + $O\Ascon.obj \ + $O\Cascade.obj \ + $O\CascadeRegister.obj \ + $O\HkdfBlake2sp.obj \ + $O\HmacSha256.obj \ + $O\HmacSha512.obj \ $O\MyAes.obj \ $O\MyAesReg.obj \ + $O\Pbkdf2HmacSha512.obj \ + $O\XChaCha20.obj \ + $O\XChaCha20Register.obj \ + $O\XChaCha20Poly1305.obj \ + $O\XChaCha20Poly1305Register.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ $O\Bcj2.obj \ + $O\Blake2s.obj \ $O\Bra.obj \ $O\Bra86.obj \ $O\BraIA64.obj \ @@ -112,5 +125,6 @@ C_OBJS = \ !include "../../Crc.mak" !include "../../LzmaDec.mak" !include "../../Sha256.mak" +!include "../../Sha512.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/Format7zF/Arc.mak b/CPP/7zip/Bundles/Format7zF/Arc.mak index b1c6fe22..533da499 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc.mak @@ -14,7 +14,6 @@ COMMON_OBJS = \ $O\Sha256Reg.obj \ $O\Sha3Reg.obj \ $O\Sha512Reg.obj \ - $O\Sha512Prepare.obj \ $O\StringConvert.obj \ $O\StringToInt.obj \ $O\UTFConvert.obj \ @@ -244,11 +243,22 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ + $O\7zKeyDerivation.obj \ + $O\Ascon.obj \ + $O\Cascade.obj \ + $O\CascadeRegister.obj \ + $O\HkdfBlake2sp.obj \ + $O\XChaCha20.obj \ + $O\XChaCha20Register.obj \ + $O\XChaCha20Poly1305.obj \ + $O\XChaCha20Poly1305Register.obj \ $O\HmacSha1.obj \ $O\HmacSha256.obj \ + $O\HmacSha512.obj \ $O\MyAes.obj \ $O\MyAesReg.obj \ $O\Pbkdf2HmacSha1.obj \ + $O\Pbkdf2HmacSha512.obj \ $O\RandGen.obj \ $O\Rar20Crypto.obj \ $O\Rar5Aes.obj \ @@ -289,8 +299,6 @@ C_OBJS = \ $O\Ppmd8Dec.obj \ $O\Ppmd8Enc.obj \ $O\Sha3.obj \ - $O\Sha512.obj \ - $O\Sha512Opt.obj \ $O\SwapBytes.obj \ $O\Threads.obj \ $O\Xxh64.obj \ @@ -307,4 +315,5 @@ C_OBJS = \ !include "../../LzmaDec.mak" !include "../../Sha1.mak" !include "../../Sha256.mak" +!include "../../Sha512.mak" !include "../../Sort.mak" diff --git a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak index 746aaff2..07933d6a 100644 --- a/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak +++ b/CPP/7zip/Bundles/Format7zF/Arc_gcc.mak @@ -298,13 +298,24 @@ endif CRYPTO_OBJS = \ $O/7zAes.o \ $O/7zAesRegister.o \ + $O/7zKeyDerivation.o \ + $O/Ascon.o \ + $O/Cascade.o \ + $O/CascadeRegister.o \ + $O/HkdfBlake2sp.o \ $O/HmacSha1.o \ $O/HmacSha256.o \ + $O/HmacSha512.o \ $O/MyAes.o \ $O/MyAesReg.o \ $O/Pbkdf2HmacSha1.o \ + $O/Pbkdf2HmacSha512.o \ $O/RandGen.o \ $O/WzAes.o \ + $O/XChaCha20.o \ + $O/XChaCha20Poly1305.o \ + $O/XChaCha20Poly1305Register.o \ + $O/XChaCha20Register.o \ $O/ZipCrypto.o \ $O/ZipStrong.o \ diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp index cf91341d..7243f7ec 100644 --- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp +++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp @@ -1147,6 +1147,24 @@ SOURCE=..\..\Crypto\7zAesRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Crypto\7zKeyDerivation.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zKeyDerivation.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\HmacSha1.cpp !IF "$(CFG)" == "7z - Win32 Release" @@ -1183,6 +1201,24 @@ SOURCE=..\..\Crypto\HmacSha256.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\HmacSha512.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha512.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\MyAes.cpp !IF "$(CFG)" == "7z - Win32 Release" @@ -1233,6 +1269,24 @@ SOURCE=..\..\Crypto\Pbkdf2HmacSha1.h # End Source File # Begin Source File +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.cpp + +!IF "$(CFG)" == "7z - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\RandGen.cpp !IF "$(CFG)" == "7z - Win32 Release" diff --git a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp index d4909326..2b03996e 100644 --- a/CPP/7zip/Bundles/SFXCon/SFXCon.dsp +++ b/CPP/7zip/Bundles/SFXCon/SFXCon.dsp @@ -357,12 +357,96 @@ SOURCE=..\..\Crypto\7zAesRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Crypto\7zKeyDerivation.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zKeyDerivation.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha512.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha512.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\MyAes.cpp # End Source File # Begin Source File SOURCE=..\..\Crypto\MyAes.h # End Source File +# Begin Source File + +SOURCE=..\..\Crypto\XChaCha20.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\XChaCha20.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\XChaCha20Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\XChaCha20Poly1305.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\XChaCha20Poly1305.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\XChaCha20Poly1305Register.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Cascade.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Cascade.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\CascadeRegister.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Ascon.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Ascon.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\AsconSimd.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\ChaCha20Simd.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HkdfBlake2sp.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HkdfBlake2sp.h +# End Source File # End Group # Begin Group "Windows" @@ -529,6 +613,10 @@ SOURCE=..\..\..\Common\Sha256Prepare.cpp # End Source File # Begin Source File +SOURCE=..\..\..\Common\Sha512Prepare.cpp +# End Source File +# Begin Source File + SOURCE=..\..\..\Common\StdInStream.cpp # End Source File # Begin Source File @@ -973,6 +1061,29 @@ SOURCE=..\..\..\..\C\Sha256Opt.c # End Source File # Begin Source File +SOURCE=..\..\..\..\C\Sha512.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha512.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Sha512Opt.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Blake2s.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\C\Blake2.h +# End Source File +# Begin Source File + SOURCE=..\..\..\..\C\Threads.c # SUBTRACT CPP /YX /Yc /Yu # End Source File diff --git a/CPP/7zip/Bundles/SFXCon/makefile b/CPP/7zip/Bundles/SFXCon/makefile index a72e3f8f..ffd0a14d 100644 --- a/CPP/7zip/Bundles/SFXCon/makefile +++ b/CPP/7zip/Bundles/SFXCon/makefile @@ -109,11 +109,23 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ + $O\7zKeyDerivation.obj \ + $O\HkdfBlake2sp.obj \ + $O\HmacSha512.obj \ + $O\Pbkdf2HmacSha512.obj \ + $O\Ascon.obj \ + $O\Cascade.obj \ + $O\CascadeRegister.obj \ $O\MyAes.obj \ + $O\XChaCha20.obj \ + $O\XChaCha20Register.obj \ + $O\XChaCha20Poly1305.obj \ + $O\XChaCha20Poly1305Register.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ + $O\Blake2s.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ @@ -133,5 +145,6 @@ C_OBJS = \ !include "../../Crc.mak" !include "../../LzmaDec.mak" !include "../../Sha256.mak" +!include "../../Sha512.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Bundles/SFXCon/makefile.gcc b/CPP/7zip/Bundles/SFXCon/makefile.gcc index 28abdf74..8c489938 100644 --- a/CPP/7zip/Bundles/SFXCon/makefile.gcc +++ b/CPP/7zip/Bundles/SFXCon/makefile.gcc @@ -90,6 +90,7 @@ COMMON_OBJS = \ $O/MyVector.o \ $O/NewHandler.o \ $O/Sha256Prepare.o \ + $O/Sha512Prepare.o \ $O/StdInStream.o \ $O/StdOutStream.o \ $O/StringConvert.o \ @@ -171,12 +172,25 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O/7zAes.o \ $O/7zAesRegister.o \ + $O/7zKeyDerivation.o \ + $O/Ascon.o \ + $O/Cascade.o \ + $O/CascadeRegister.o \ + $O/HkdfBlake2sp.o \ + $O/HmacSha256.o \ + $O/HmacSha512.o \ $O/MyAes.o \ + $O/Pbkdf2HmacSha512.o \ + $O/XChaCha20.o \ + $O/XChaCha20Register.o \ + $O/XChaCha20Poly1305.o \ + $O/XChaCha20Poly1305Register.o \ C_OBJS = \ $O/7zStream.o \ $O/Alloc.o \ $O/Bcj2.o \ + $O/Blake2s.o \ $O/Bra.o \ $O/Bra86.o \ $O/BraIA64.o \ @@ -190,6 +204,8 @@ C_OBJS = \ $O/Ppmd7Dec.o \ $O/Sha256.o \ $O/Sha256Opt.o \ + $O/Sha512.o \ + $O/Sha512Opt.o \ $O/7zCrc.o \ $O/7zCrcOpt.o \ $O/Aes.o \ diff --git a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp index 18db7f83..2af02862 100644 --- a/CPP/7zip/Bundles/SFXWin/SFXWin.dsp +++ b/CPP/7zip/Bundles/SFXWin/SFXWin.dsp @@ -313,6 +313,30 @@ SOURCE=..\..\Crypto\7zAesRegister.cpp # End Source File # Begin Source File +SOURCE=..\..\Crypto\7zKeyDerivation.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\7zKeyDerivation.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha512.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\HmacSha512.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Pbkdf2HmacSha512.h +# End Source File +# Begin Source File + SOURCE=..\..\Crypto\MyAes.cpp # End Source File # Begin Source File diff --git a/CPP/7zip/Bundles/SFXWin/makefile b/CPP/7zip/Bundles/SFXWin/makefile index 806bd073..744ff5ea 100644 --- a/CPP/7zip/Bundles/SFXWin/makefile +++ b/CPP/7zip/Bundles/SFXWin/makefile @@ -131,11 +131,23 @@ COMPRESS_OBJS = \ CRYPTO_OBJS = \ $O\7zAes.obj \ $O\7zAesRegister.obj \ + $O\7zKeyDerivation.obj \ + $O\HkdfBlake2sp.obj \ + $O\HmacSha512.obj \ + $O\Pbkdf2HmacSha512.obj \ + $O\Ascon.obj \ + $O\Cascade.obj \ + $O\CascadeRegister.obj \ $O\MyAes.obj \ + $O\XChaCha20.obj \ + $O\XChaCha20Register.obj \ + $O\XChaCha20Poly1305.obj \ + $O\XChaCha20Poly1305Register.obj \ C_OBJS = \ $O\7zStream.obj \ $O\Alloc.obj \ + $O\Blake2s.obj \ $O\Bcj2.obj \ $O\Bra.obj \ $O\Bra86.obj \ @@ -155,5 +167,6 @@ C_OBJS = \ !include "../../Crc.mak" !include "../../LzmaDec.mak" !include "../../Sha256.mak" +!include "../../Sha512.mak" !include "../../7zip.mak" diff --git a/CPP/7zip/Common/CreateCoder.cpp b/CPP/7zip/Common/CreateCoder.cpp index 93113a0a..67873d14 100644 --- a/CPP/7zip/Common/CreateCoder.cpp +++ b/CPP/7zip/Common/CreateCoder.cpp @@ -2,7 +2,7 @@ #include "StdAfx.h" -#include "../../Windows/Defs.h" +#include "../../Windows/WinDefs.h" #include "../../Windows/PropVariant.h" #include "CreateCoder.h" diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp index 8d7e0dcc..0b5d4204 100644 --- a/CPP/7zip/Common/FilterCoder.cpp +++ b/CPP/7zip/Common/FilterCoder.cpp @@ -546,6 +546,9 @@ Z7_COM7F_IMF(CFilterCoder::SetKey(const Byte *data, UInt32 size)) Z7_COM7F_IMF(CFilterCoder::SetInitVector(const Byte *data, UInt32 size)) { return _cryptoProperties->SetInitVector(data, size); } +Z7_COM7F_IMF(CFilterCoder::CryptoAuthVerify(Int32 *result)) + { return _cryptoAuthVerify->CryptoAuthVerify(result); } + #endif diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h index 3a588fd5..2e3bf9da 100644 --- a/CPP/7zip/Common/FilterCoder.h +++ b/CPP/7zip/Common/FilterCoder.h @@ -45,6 +45,7 @@ class CFilterCoder Z7_final : #ifndef Z7_NO_CRYPTO public ICryptoSetPassword, public ICryptoProperties, + public ICryptoAuthVerify, #endif #ifndef Z7_EXTRACT_ONLY @@ -92,6 +93,7 @@ class CFilterCoder Z7_final : #ifndef Z7_NO_CRYPTO CMyComPtr _setPassword; CMyComPtr _cryptoProperties; + CMyComPtr _cryptoAuthVerify; #endif #ifndef Z7_EXTRACT_ONLY @@ -148,6 +150,7 @@ class CFilterCoder Z7_final : #ifndef Z7_NO_CRYPTO Z7_COM_QI_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword) Z7_COM_QI_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties) + Z7_COM_QI_ENTRY_AG(ICryptoAuthVerify, Filter, _cryptoAuthVerify) #endif #ifndef Z7_EXTRACT_ONLY @@ -182,6 +185,7 @@ class CFilterCoder Z7_final : #ifndef Z7_NO_CRYPTO Z7_IFACE_COM7_IMP(ICryptoSetPassword) Z7_IFACE_COM7_IMP(ICryptoProperties) + Z7_IFACE_COM7_IMP(ICryptoAuthVerify) #endif #ifndef Z7_EXTRACT_ONLY diff --git a/CPP/7zip/Common/MethodProps.h b/CPP/7zip/Common/MethodProps.h index be108fa2..f7ba5690 100644 --- a/CPP/7zip/Common/MethodProps.h +++ b/CPP/7zip/Common/MethodProps.h @@ -6,8 +6,7 @@ #include "../../Common/MyString.h" #include "../../Common/Defs.h" -#include "../../Windows/Defs.h" - +#include "../../Windows/WinDefs.h" #include "../../Windows/PropVariant.h" #include "../ICoder.h" diff --git a/CPP/7zip/Common/PropId.cpp b/CPP/7zip/Common/PropId.cpp index 6117b0e2..b00ad813 100644 --- a/CPP/7zip/Common/PropId.cpp +++ b/CPP/7zip/Common/PropId.cpp @@ -3,10 +3,8 @@ #include "StdAfx.h" #include "../../Common/MyWindows.h" - #include "../PropID.h" -// VARTYPE const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = { VT_EMPTY, @@ -84,7 +82,7 @@ const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] = VT_UI4, VT_BSTR, VT_UI8, - VT_UI8, + VT_UI4, // kpidNumAltStreams VT_UI8, VT_UI8, VT_UI8, diff --git a/CPP/7zip/Compress/CodecExports.cpp b/CPP/7zip/Compress/CodecExports.cpp index e37ae143..70be7602 100644 --- a/CPP/7zip/Compress/CodecExports.cpp +++ b/CPP/7zip/Compress/CodecExports.cpp @@ -8,7 +8,7 @@ #include "../../Common/ComTry.h" #include "../../Common/MyCom.h" -#include "../../Windows/Defs.h" +#include "../../Windows/WinDefs.h" #include "../../Windows/PropVariant.h" #include "../ICoder.h" diff --git a/CPP/7zip/Crypto/7zAes.cpp b/CPP/7zip/Crypto/7zAes.cpp index b2031050..aebc52d6 100644 --- a/CPP/7zip/Crypto/7zAes.cpp +++ b/CPP/7zip/Crypto/7zAes.cpp @@ -3,10 +3,8 @@ #include "StdAfx.h" #include "../../../C/CpuArch.h" -#include "../../../C/Sha256.h" #include "../../Common/ComTry.h" -#include "../../Common/MyBuffer2.h" #ifndef Z7_ST #include "../../Windows/Synchronization.h" @@ -26,132 +24,6 @@ namespace N7z { static const unsigned k_NumCyclesPower_Supported_MAX = 24; -bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const -{ - if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower) - return false; - for (unsigned i = 0; i < SaltSize; i++) - if (Salt[i] != a.Salt[i]) - return false; - return (Password == a.Password); -} - -void CKeyInfo::CalcKey() -{ - if (NumCyclesPower == 0x3F) - { - unsigned pos; - for (pos = 0; pos < SaltSize; pos++) - Key[pos] = Salt[pos]; - for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++) - Key[pos++] = Password[i]; - for (; pos < kKeySize; pos++) - Key[pos] = 0; - } - else - { - const unsigned kUnrPow = 6; - const UInt32 numUnroll = (UInt32)1 << (NumCyclesPower <= kUnrPow ? (unsigned)NumCyclesPower : kUnrPow); - - const size_t bufSize = 8 + SaltSize + Password.Size(); - const size_t unrollSize = bufSize * numUnroll; - - // MY_ALIGN (16) - // CSha256 sha; - const size_t shaAllocSize = sizeof(CSha256) + unrollSize + bufSize * 2; - CAlignedBuffer1 sha(shaAllocSize); - Byte *buf = sha + sizeof(CSha256); - - memcpy(buf, Salt, SaltSize); - memcpy(buf + SaltSize, Password, Password.Size()); - memset(buf + bufSize - 8, 0, 8); - - Sha256_Init((CSha256 *)(void *)(Byte *)sha); - - { - { - Byte *dest = buf; - for (UInt32 i = 1; i < numUnroll; i++) - { - dest += bufSize; - memcpy(dest, buf, bufSize); - } - } - - const UInt32 numRounds = (UInt32)1 << NumCyclesPower; - UInt32 r = 0; - do - { - Byte *dest = buf + bufSize - 8; - UInt32 i = r; - r += numUnroll; - do - { - SetUi32(dest, i) i++; dest += bufSize; - // SetUi32(dest, i) i++; dest += bufSize; - } - while (i < r); - Sha256_Update((CSha256 *)(void *)(Byte *)sha, buf, unrollSize); - } - while (r < numRounds); - } - /* - UInt64 numRounds = (UInt64)1 << NumCyclesPower; - - do - { - Sha256_Update((CSha256 *)(Byte *)sha, buf, bufSize); - for (unsigned i = 0; i < 8; i++) - if (++(ctr[i]) != 0) - break; - } - while (--numRounds != 0); - */ - - Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key); - memset(sha, 0, shaAllocSize); - } -} - -bool CKeyInfoCache::GetKey(CKeyInfo &key) -{ - FOR_VECTOR (i, Keys) - { - const CKeyInfo &cached = Keys[i]; - if (key.IsEqualTo(cached)) - { - for (unsigned j = 0; j < kKeySize; j++) - key.Key[j] = cached.Key[j]; - if (i != 0) - Keys.MoveToFront(i); - return true; - } - } - return false; -} - -void CKeyInfoCache::FindAndAdd(const CKeyInfo &key) -{ - FOR_VECTOR (i, Keys) - { - const CKeyInfo &cached = Keys[i]; - if (key.IsEqualTo(cached)) - { - if (i != 0) - Keys.MoveToFront(i); - return; - } - } - Add(key); -} - -void CKeyInfoCache::Add(const CKeyInfo &key) -{ - if (Keys.Size() >= Size) - Keys.DeleteBack(); - Keys.Insert(0, key); -} - static CKeyInfoCache g_GlobalKeyCache(32); #ifndef Z7_ST @@ -171,7 +43,6 @@ CBase::CBase(): void CBase::PrepareKey() { - // BCJ2 threads use same password. So we use long lock. MT_LOCK bool finded = false; @@ -188,15 +59,6 @@ void CBase::PrepareKey() #ifndef Z7_EXTRACT_ONLY -/* -Z7_COM7F_IMF(CEncoder::ResetSalt()) -{ - _key.SaltSize = 4; - g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); - return S_OK; -} -*/ - Z7_COM7F_IMF(CEncoder::ResetInitVector()) { for (unsigned i = 0; i < sizeof(_iv); i++) @@ -231,8 +93,6 @@ Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) CEncoder::CEncoder() { - // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize); - // _key.NumCyclesPower = 0x3F; _key.NumCyclesPower = 19; _aesFilter = new CAesCbcEncoder(kKeySize); } diff --git a/CPP/7zip/Crypto/7zAes.h b/CPP/7zip/Crypto/7zAes.h index 8f7bf03e..66d33413 100644 --- a/CPP/7zip/Crypto/7zAes.h +++ b/CPP/7zip/Crypto/7zAes.h @@ -3,66 +3,22 @@ #ifndef ZIP7_INC_CRYPTO_7Z_AES_H #define ZIP7_INC_CRYPTO_7Z_AES_H -#include "../../Common/MyBuffer.h" #include "../../Common/MyCom.h" -#include "../../Common/MyVector.h" #include "../ICoder.h" #include "../IPassword.h" +#include "7zKeyDerivation.h" + namespace NCrypto { namespace N7z { -const unsigned kKeySize = 32; -const unsigned kSaltSizeMax = 16; -const unsigned kIvSizeMax = 16; // AES_BLOCK_SIZE; - -class CKeyInfo -{ -public: - unsigned NumCyclesPower; - unsigned SaltSize; - Byte Salt[kSaltSizeMax]; - CByteBuffer Password; - Byte Key[kKeySize]; - - bool IsEqualTo(const CKeyInfo &a) const; - void CalcKey(); - - CKeyInfo() { ClearProps(); } - void ClearProps() - { - NumCyclesPower = 0; - SaltSize = 0; - for (unsigned i = 0; i < sizeof(Salt); i++) - Salt[i] = 0; - } - - void Wipe() - { - Password.Wipe(); - NumCyclesPower = 0; - SaltSize = 0; - Z7_memset_0_ARRAY(Salt); - Z7_memset_0_ARRAY(Key); - } +using CKeyInfo = N7zKeyDerivation::CKeyInfo; +using CKeyInfoCache = N7zKeyDerivation::CKeyInfoCache; -#ifdef Z7_CPP_IS_SUPPORTED_default - CKeyInfo(const CKeyInfo &) = default; -#endif - ~CKeyInfo() { Wipe(); } -}; +using N7zKeyDerivation::kKeySize; -class CKeyInfoCache -{ - unsigned Size; - CObjectVector Keys; -public: - CKeyInfoCache(unsigned size): Size(size) {} - bool GetKey(CKeyInfo &key); - void Add(const CKeyInfo &key); - void FindAndAdd(const CKeyInfo &key); -}; +const unsigned kIvSizeMax = 16; class CBase { @@ -74,6 +30,10 @@ class CBase void PrepareKey(); CBase(); + ~CBase() + { + Z7_memset_0_ARRAY(_iv); + } }; class CBaseCoder: @@ -94,17 +54,14 @@ class CBaseCoder: class CEncoder Z7_final: public CBaseCoder, public ICompressWriteCoderProperties, - // public ICryptoResetSalt, public ICryptoResetInitVector { Z7_COM_UNKNOWN_IMP_4( ICompressFilter, ICryptoSetPassword, ICompressWriteCoderProperties, - // ICryptoResetSalt, ICryptoResetInitVector) Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties) - // Z7_IFACE_COM7_IMP(ICryptoResetSalt) Z7_IFACE_COM7_IMP(ICryptoResetInitVector) public: CEncoder(); diff --git a/CPP/7zip/Crypto/7zKeyDerivation.cpp b/CPP/7zip/Crypto/7zKeyDerivation.cpp new file mode 100644 index 00000000..c7b3da3d --- /dev/null +++ b/CPP/7zip/Crypto/7zKeyDerivation.cpp @@ -0,0 +1,159 @@ +// 7zKeyDerivation.cpp +// Key derivation common module for 7z format + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" +#include "../../../C/Sha256.h" + +#include "../../Common/MyBuffer2.h" + +#include "7zKeyDerivation.h" +#include "Pbkdf2HmacSha512.h" + +namespace NCrypto { +namespace N7zKeyDerivation { + +static bool ConstantTimeCompare(const Byte *a, const Byte *b, size_t size) +{ +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4746) +#endif + volatile Byte result = 0; + for (size_t i = 0; i < size; i++) + result |= a[i] ^ b[i]; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + return result == 0; +} + +bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const +{ + if (DerivMode != a.DerivMode) + return false; + if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower) + return false; + if (!ConstantTimeCompare(Salt, a.Salt, SaltSize)) + return false; + if (Password.Size() != a.Password.Size()) + return false; + return ConstantTimeCompare(Password, a.Password, Password.Size()); +} + +void CKeyInfo::CalcKey() +{ + if (DerivMode == kDeriv_Cascade) + { + // PBKDF2-HMAC-SHA512, output 96 bytes + const UInt32 numIterations = (NumCyclesPower == 0x3F) ? + 1 : (UInt32)1 << NumCyclesPower; + NSha512::Pbkdf2Hmac( + Password, Password.Size(), + Salt, SaltSize, + numIterations, + CascadeKey, kCascadeKeySize); + } + else if (NumCyclesPower == 0x3F) + { + unsigned pos; + for (pos = 0; pos < SaltSize; pos++) + Key[pos] = Salt[pos]; + for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++) + Key[pos++] = Password[i]; + for (; pos < kKeySize; pos++) + Key[pos] = 0; + } + else + { + const unsigned kUnrPow = 6; + const UInt32 numUnroll = (UInt32)1 << (NumCyclesPower <= kUnrPow ? (unsigned)NumCyclesPower : kUnrPow); + + const size_t bufSize = 8 + SaltSize + Password.Size(); + const size_t unrollSize = bufSize * numUnroll; + + const size_t shaAllocSize = sizeof(CSha256) + unrollSize + bufSize * 2; + CAlignedBuffer1 sha(shaAllocSize); + Byte *buf = sha + sizeof(CSha256); + + memcpy(buf, Salt, SaltSize); + memcpy(buf + SaltSize, Password, Password.Size()); + memset(buf + bufSize - 8, 0, 8); + + Sha256_Init((CSha256 *)(void *)(Byte *)sha); + + { + { + Byte *dest = buf; + for (UInt32 i = 1; i < numUnroll; i++) + { + dest += bufSize; + memcpy(dest, buf, bufSize); + } + } + + const UInt32 numRounds = (UInt32)1 << NumCyclesPower; + UInt32 r = 0; + do + { + Byte *dest = buf + bufSize - 8; + UInt32 i = r; + r += numUnroll; + do + { + SetUi32(dest, i); i++; dest += bufSize; + } + while (i < r); + Sha256_Update((CSha256 *)(void *)(Byte *)sha, buf, unrollSize); + } + while (r < numRounds); + } + + Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key); + memset(sha, 0, shaAllocSize); + } +} + +bool CKeyInfoCache::GetKey(CKeyInfo &key) +{ + FOR_VECTOR (i, Keys) + { + const CKeyInfo &cached = Keys[i]; + if (key.IsEqualTo(cached)) + { + if (cached.DerivMode == kDeriv_Cascade) + memcpy(key.CascadeKey, cached.CascadeKey, kCascadeKeySize); + else + memcpy(key.Key, cached.Key, kKeySize); + if (i != 0) + Keys.MoveToFront(i); + return true; + } + } + return false; +} + +void CKeyInfoCache::FindAndAdd(const CKeyInfo &key) +{ + FOR_VECTOR (i, Keys) + { + const CKeyInfo &cached = Keys[i]; + if (key.IsEqualTo(cached)) + { + if (i != 0) + Keys.MoveToFront(i); + return; + } + } + Add(key); +} + +void CKeyInfoCache::Add(const CKeyInfo &key) +{ + if (Keys.Size() >= Size) + Keys.DeleteBack(); + Keys.Insert(0, key); +} + +}} diff --git a/CPP/7zip/Crypto/7zKeyDerivation.h b/CPP/7zip/Crypto/7zKeyDerivation.h new file mode 100644 index 00000000..1d688233 --- /dev/null +++ b/CPP/7zip/Crypto/7zKeyDerivation.h @@ -0,0 +1,81 @@ +// 7zKeyDerivation.h +// Key derivation common module for 7z format + +#ifndef ZIP7_INC_CRYPTO_7Z_KEY_DERIVATION_H +#define ZIP7_INC_CRYPTO_7Z_KEY_DERIVATION_H + +#include "../../Common/MyBuffer.h" +#include "../../Common/MyVector.h" + +namespace NCrypto { +namespace N7zKeyDerivation { + +const unsigned kKeySize = 32; +const unsigned kSaltSizeMax = 32; + +// for cascade mode +const unsigned kCascadeKeySize = 96; + +// random salt for cascade mode +const unsigned kCascadeSaltSize = 32; + +enum EDerivationMode +{ + kDeriv_Single = 0, // SHA-256 iterative + kDeriv_Cascade = 1 // PBKDF2-HMAC-SHA512 +}; + +class CKeyInfo +{ +public: + unsigned NumCyclesPower; + unsigned SaltSize; + Byte Salt[kSaltSizeMax]; + CByteBuffer Password; + Byte Key[kKeySize]; + EDerivationMode DerivMode; + Byte CascadeKey[kCascadeKeySize]; + + bool IsEqualTo(const CKeyInfo &a) const; + void CalcKey(); + + CKeyInfo() { ClearProps(); } + void ClearProps() + { + NumCyclesPower = 0; + SaltSize = 0; + DerivMode = kDeriv_Single; + for (unsigned i = 0; i < sizeof(Salt); i++) + Salt[i] = 0; + } + + void Wipe() + { + Password.Wipe(); + NumCyclesPower = 0; + SaltSize = 0; + Z7_memset_0_ARRAY(Salt); + Z7_memset_0_ARRAY(Key); + Z7_memset_0_ARRAY(CascadeKey); + } + +#ifdef Z7_CPP_IS_SUPPORTED_default + CKeyInfo(const CKeyInfo &) = default; +#endif + ~CKeyInfo() { Wipe(); } +}; + +class CKeyInfoCache +{ + unsigned Size; + CObjectVector Keys; +public: + CKeyInfoCache(unsigned size): Size(size) {} + bool GetKey(CKeyInfo &key); + void Add(const CKeyInfo &key); + void FindAndAdd(const CKeyInfo &key); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/Ascon.cpp b/CPP/7zip/Crypto/Ascon.cpp new file mode 100644 index 00000000..2ab6b09b --- /dev/null +++ b/CPP/7zip/Crypto/Ascon.cpp @@ -0,0 +1,181 @@ +// Ascon.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "Ascon.h" +#include "AsconSimd.h" + +namespace NCrypto { +namespace NAscon { + +#ifdef MY_CPU_X86_OR_AMD64 + +bool g_SSE2Enabled = false; +bool g_SIMDInitialized = false; + +#ifdef MY_CPU_AMD64 +bool g_AVX512Enabled = false; + +static UInt64 Ascon_xgetbv(UInt32 num) +{ +#if defined(_MSC_VER) + return _xgetbv(num); +#elif defined(__GNUC__) || defined(__clang__) + UInt32 a, d; + __asm__ __volatile__("xgetbv" : "=a"(a), "=d"(d) : "c"(num) : "cc"); + return ((UInt64)d << 32) | a; +#else + return 0; +#endif +} +#endif + +void InitSIMD() +{ + if (g_SIMDInitialized) + return; + g_SIMDInitialized = true; + +#ifdef MY_CPU_AMD64 + g_SSE2Enabled = true; +#else + g_SSE2Enabled = CPU_IsSupported_SSE2() != 0; +#endif + +#ifdef MY_CPU_AMD64 + if (CPU_IsSupported_AVX()) + { + if (z7_x86_cpuid_GetMaxFunc() >= 7) + { + UInt32 d[4]; + z7_x86_cpuid(d, 7); + BoolInt avx512f = (d[1] >> 16) & 1; + BoolInt avx512vl = (d[1] >> 31) & 1; + if (avx512f && avx512vl) + { + const UInt32 bm = (UInt32)Ascon_xgetbv(0); + if ((bm & 0xE0) == 0xE0) + g_AVX512Enabled = true; + } + } + } +#endif +} + +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 + +bool g_NEONEnabled = false; +bool g_SIMDARMInitialized = false; + +void InitSIMD() +{ + if (g_SIMDARMInitialized) + return; + g_SIMDARMInitialized = true; + g_NEONEnabled = CPU_IsSupported_NEON() != 0; +} + +#endif + +#define RC0 0xf0 +#define RC1 0xe1 +#define RC2 0xd2 +#define RC3 0xc3 +#define RC4 0xb4 +#define RC5 0xa5 +#define RC6 0x96 +#define RC7 0x87 +#define RC8 0x78 +#define RC9 0x69 +#define RCa 0x5a +#define RCb 0x4b + +static Z7_FORCE_INLINE void AsconRound(UInt64 *st, UInt64 C) +{ + UInt64 x0 = st[0]; + UInt64 x1 = st[1]; + UInt64 x2 = st[2]; + UInt64 x3 = st[3]; + UInt64 x4 = st[4]; + + x2 ^= C; + x0 ^= x4; + x4 ^= x3; + x2 ^= x1; + + UInt64 t0 = x0 ^ (~x1 & x2); + UInt64 t2 = x2 ^ (~x3 & x4); + UInt64 t4 = x4 ^ (~x0 & x1); + UInt64 t1 = x1 ^ (~x2 & x3); + UInt64 t3 = x3 ^ (~x4 & x0); + t1 ^= t0; + t3 ^= t2; + t0 ^= t4; + t2 = ~t2; + + x0 = t0 ^ ASCON_ROR64(t0, 19) ^ ASCON_ROR64(t0, 28); + x1 = t1 ^ ASCON_ROR64(t1, 61) ^ ASCON_ROR64(t1, 39); + x2 = t2 ^ ASCON_ROR64(t2, 1) ^ ASCON_ROR64(t2, 6); + x3 = t3 ^ ASCON_ROR64(t3, 10) ^ ASCON_ROR64(t3, 17); + x4 = t4 ^ ASCON_ROR64(t4, 7) ^ ASCON_ROR64(t4, 41); + + st[0] = x0; + st[1] = x1; + st[2] = x2; + st[3] = x3; + st[4] = x4; +} + +void AsconP12(UInt64 state[5]) +{ +#ifdef MY_CPU_AMD64 + InitSIMD(); + if (g_AVX512Enabled) + { + UInt64 st[8] = { state[0], state[1], state[2], state[3], state[4] }; + AsconP12_AVX512(st); + state[0] = st[0]; + state[1] = st[1]; + state[2] = st[2]; + state[3] = st[3]; + state[4] = st[4]; + return; + } +#endif + AsconRound(state, RC0); AsconRound(state, RC1); + AsconRound(state, RC2); AsconRound(state, RC3); + AsconRound(state, RC4); AsconRound(state, RC5); + AsconRound(state, RC6); AsconRound(state, RC7); + AsconRound(state, RC8); AsconRound(state, RC9); + AsconRound(state, RCa); AsconRound(state, RCb); +} + +void AsconP8(UInt64 state[5]) +{ +#ifdef MY_CPU_AMD64 + InitSIMD(); + if (g_AVX512Enabled) + { + UInt64 st[8] = { state[0], state[1], state[2], state[3], state[4] }; + AsconP8_AVX512(st); + state[0] = st[0]; + state[1] = st[1]; + state[2] = st[2]; + state[3] = st[3]; + state[4] = st[4]; + return; + } +#endif + AsconRound(state, RC4); AsconRound(state, RC5); + AsconRound(state, RC6); AsconRound(state, RC7); + AsconRound(state, RC8); AsconRound(state, RC9); + AsconRound(state, RCa); AsconRound(state, RCb); +} + +}} diff --git a/CPP/7zip/Crypto/Ascon.h b/CPP/7zip/Crypto/Ascon.h new file mode 100644 index 00000000..4725db19 --- /dev/null +++ b/CPP/7zip/Crypto/Ascon.h @@ -0,0 +1,31 @@ +// Ascon.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_INC_CRYPTO_ASCON_H +#define ZIP7_INC_CRYPTO_ASCON_H + +#include "../../Common/MyCom.h" + +namespace NCrypto { +namespace NAscon { + +const unsigned kKeySize_Ascon = 16; +const unsigned kNonceSize = 16; +const unsigned kTagSize = 16; +const unsigned kRateSize = 16; + +static const UInt64 kIV_Ascon = 0x00001000808C0001ULL; + +#ifdef _MSC_VER +#include +#define ASCON_ROR64(v, n) _rotr64((v), (n)) +#else +#define ASCON_ROR64(v, n) (((v) >> (n)) | ((v) << (64 - (n)))) +#endif + +void AsconP12(UInt64 state[5]); +void AsconP8(UInt64 state[5]); + +}} +#endif diff --git a/CPP/7zip/Crypto/AsconSimd.h b/CPP/7zip/Crypto/AsconSimd.h new file mode 100644 index 00000000..5fdb2a50 --- /dev/null +++ b/CPP/7zip/Crypto/AsconSimd.h @@ -0,0 +1,156 @@ +// AsconSimd.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_INC_CRYPTO_ASCON_SIMD_H +#define ZIP7_INC_CRYPTO_ASCON_SIMD_H + +#include "Ascon.h" + +#ifdef MY_CPU_SSE2 +#include +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 +#include +#endif + +namespace NCrypto { +namespace NAscon { + +#ifdef MY_CPU_X86_OR_AMD64 + +extern bool g_SSE2Enabled; +extern bool g_SIMDInitialized; + +#ifdef MY_CPU_AMD64 +extern bool g_AVX512Enabled; +#endif + +void InitSIMD(); + +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 + +extern bool g_NEONEnabled; +extern bool g_SIMDARMInitialized; + +void InitSIMD(); + +#endif + +#ifdef MY_CPU_SSE2 + +static Z7_FORCE_INLINE void AsconEncBlock_SSE2(UInt64 state[5], Byte *data) +{ + __m128i ks = _mm_set_epi64x(state[1], state[0]); + __m128i ct = _mm_xor_si128(_mm_loadu_si128((const __m128i*)data), ks); + _mm_storeu_si128((__m128i*)data, ct); + _mm_storel_epi64((__m128i*)&state[0], ct); + _mm_storel_epi64((__m128i*)&state[1], _mm_srli_si128(ct, 8)); +} + +static Z7_FORCE_INLINE void AsconDecBlock_SSE2(UInt64 state[5], Byte *data) +{ + __m128i ks = _mm_set_epi64x(state[1], state[0]); + __m128i ct = _mm_loadu_si128((const __m128i*)data); + __m128i pt = _mm_xor_si128(ct, ks); + _mm_storeu_si128((__m128i*)data, pt); + _mm_storel_epi64((__m128i*)&state[0], ct); + _mm_storel_epi64((__m128i*)&state[1], _mm_srli_si128(ct, 8)); +} + +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 + +static Z7_FORCE_INLINE void AsconEncBlock_NEON(UInt64 state[5], Byte *data) +{ + uint64x2_t ks = vld1q_u64((const uint64_t*)state); + uint64x2_t pt = vld1q_u64((const uint64_t*)data); + uint64x2_t ct = veorq_u64(pt, ks); + vst1q_u64((uint64_t*)data, ct); + state[0] = vgetq_lane_u64(ct, 0); + state[1] = vgetq_lane_u64(ct, 1); +} + +static Z7_FORCE_INLINE void AsconDecBlock_NEON(UInt64 state[5], Byte *data) +{ + uint64x2_t ks = vld1q_u64((const uint64_t*)state); + uint64x2_t ct = vld1q_u64((const uint64_t*)data); + uint64x2_t pt = veorq_u64(ct, ks); + vst1q_u64((uint64_t*)data, pt); + state[0] = vgetq_lane_u64(ct, 0); + state[1] = vgetq_lane_u64(ct, 1); +} + +#endif + +#ifdef MY_CPU_AMD64 + +#include + +#if defined(__GNUC__) || defined(__clang__) +#define Z7_AVX512_TARGET __attribute__((target("avx512f"))) +#else +#define Z7_AVX512_TARGET +#endif + +static Z7_AVX512_TARGET Z7_FORCE_INLINE void AsconRound_AVX512(UInt64 *st, UInt64 C) +{ + const UInt64 z = 0; + const __mmask8 mxor1 = 0x15; + const __mmask8 mxor2 = 0x0b; + const __m512i pxor1 = _mm512_set_epi64(z, z, z, 3, z, 1, z, 4); + const __m512i pxor2 = _mm512_set_epi64(z, z, z, z, 2, z, 0, 4); + const __m512i rc = _mm512_set_epi64(z, z, z, 0, 0, C, 0, 0); + const __m512i neg = _mm512_set_epi64(z, z, z, 0, 0, ~(UInt64)0, 0, 0); + const __m512i pchi1 = _mm512_set_epi64(z, z, z, 0, 4, 3, 2, 1); + const __m512i pchi2 = _mm512_set_epi64(z, z, z, 1, 0, 4, 3, 2); + const __m512i rot1 = _mm512_set_epi64(z, z, z, 7, 10, 1, 61, 19); + const __m512i rot2 = _mm512_set_epi64(z, z, z, 41, 17, 6, 39, 28); + + __m512i s = _mm512_loadu_si512((const void*)st); + __m512i t0, t1, t2; + + t0 = _mm512_maskz_permutexvar_epi64(mxor1, pxor1, s); + t0 = _mm512_ternarylogic_epi64(s, t0, rc, 0x96); + + t1 = _mm512_permutexvar_epi64(pchi1, t0); + t2 = _mm512_permutexvar_epi64(pchi2, t0); + t0 = _mm512_ternarylogic_epi64(t0, t1, t2, 0xd2); + + t1 = _mm512_maskz_permutexvar_epi64(mxor2, pxor2, t0); + t0 = _mm512_ternarylogic_epi64(t0, t1, neg, 0x96); + + t1 = _mm512_rorv_epi64(t0, rot1); + t2 = _mm512_rorv_epi64(t0, rot2); + s = _mm512_ternarylogic_epi64(t0, t1, t2, 0x96); + + _mm512_storeu_si512((void*)st, s); +} + +static Z7_AVX512_TARGET inline void AsconP12_AVX512(UInt64 state[5]) +{ + AsconRound_AVX512(state, 0xf0); AsconRound_AVX512(state, 0xe1); + AsconRound_AVX512(state, 0xd2); AsconRound_AVX512(state, 0xc3); + AsconRound_AVX512(state, 0xb4); AsconRound_AVX512(state, 0xa5); + AsconRound_AVX512(state, 0x96); AsconRound_AVX512(state, 0x87); + AsconRound_AVX512(state, 0x78); AsconRound_AVX512(state, 0x69); + AsconRound_AVX512(state, 0x5a); AsconRound_AVX512(state, 0x4b); +} + +static Z7_AVX512_TARGET inline void AsconP8_AVX512(UInt64 state[5]) +{ + AsconRound_AVX512(state, 0xb4); AsconRound_AVX512(state, 0xa5); + AsconRound_AVX512(state, 0x96); AsconRound_AVX512(state, 0x87); + AsconRound_AVX512(state, 0x78); AsconRound_AVX512(state, 0x69); + AsconRound_AVX512(state, 0x5a); AsconRound_AVX512(state, 0x4b); +} + +#endif + +}} + +#endif diff --git a/CPP/7zip/Crypto/Cascade.cpp b/CPP/7zip/Crypto/Cascade.cpp new file mode 100644 index 00000000..0dd77076 --- /dev/null +++ b/CPP/7zip/Crypto/Cascade.cpp @@ -0,0 +1,1282 @@ +// Cascade.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" +#include "../../../C/Aes.h" + +#include "../../Common/ComTry.h" + +#ifndef Z7_ST +#include "../../Windows/Synchronization.h" +#endif + +#include "../Common/StreamUtils.h" + +#include "Cascade.h" +#include "HkdfBlake2sp.h" +#include "XChaCha20.h" +#include "AsconSimd.h" + +#ifndef Z7_EXTRACT_ONLY +#include "RandGen.h" +#endif + +namespace NCrypto { + +static AES_CODE_FUNC s_AesCtrFunc = NULL; + +static void InitAesCtrFunc() +{ + if (s_AesCtrFunc) + return; + + AES_CODE_FUNC func = AesCtr_Code; + +#if defined(MY_CPU_X86_OR_AMD64) + if (CPU_IsSupported_AES()) + { + func = AesCtr_Code_HW; + if (CPU_IsSupported_VAES_AVX2()) + func = AesCtr_Code_HW_256; + } +#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) + if (CPU_IsSupported_AES()) + { + func = AesCtr_Code_HW; + } +#endif + + s_AesCtrFunc = func; +} + +static void XorBytes(Byte *dst, const Byte *src, unsigned len) +{ + Byte *d = dst; + const Byte *s = src; + +#ifdef MY_CPU_LE_UNALIGN_64 + while (len >= 8) + { + *(UInt64 *)d ^= *(const UInt64 *)s; + d += 8; + s += 8; + len -= 8; + } +#endif + +#ifdef MY_CPU_LE_UNALIGN + while (len >= 4) + { + *(UInt32 *)d ^= *(const UInt32 *)s; + d += 4; + s += 4; + len -= 4; + } +#endif + + while (len--) + *d++ ^= *s++; +} + +namespace NAXPCascade { + +static CKeyInfoCache g_AXP_GlobalKeyCache(32); + +#ifndef Z7_ST + static NWindows::NSynchronization::CCriticalSection g_AXP_GlobalKeyCacheCriticalSection; + #define AXP_MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_AXP_GlobalKeyCacheCriticalSection); +#else + #define AXP_MT_LOCK +#endif + +CAXPBase::CAXPBase(): + _cachedKeys(16), + _keyDerived(false), + _aesKeys(AES_NUM_IVMRK_WORDS * sizeof(UInt32)), + _xcBlockPos(64), + _xcCounter(0), + _aadSize(0), + _finalized(false), + _authOk(false) +{ + _key.DerivMode = N7zKeyDerivation::kDeriv_Cascade; + Z7_memset_0_ARRAY(_keyAes); + Z7_memset_0_ARRAY(_aesIv); + memset(_aesKeys, 0, AES_NUM_IVMRK_WORDS * sizeof(UInt32)); + Z7_memset_0_ARRAY(_keyXChaCha20); + Z7_memset_0_ARRAY(_xcNonce); + Z7_memset_0_ARRAY(_xcDerivedKey); + Z7_memset_0_ARRAY(_xcBlock); + Z7_memset_0_ARRAY(_polyKey); +} + +void CAXPBase::PrepareKey() +{ + AXP_MT_LOCK + + bool finded = false; + if (!_cachedKeys.GetKey(_key)) + { + finded = g_AXP_GlobalKeyCache.GetKey(_key); + if (!finded) + _key.CalcKey(); + _cachedKeys.Add(_key); + } + if (!finded) + g_AXP_GlobalKeyCache.FindAndAdd(_key); + _keyDerived = false; +} + +void CAXPBase::DeriveAXPKeys() +{ + NHkdfBlake2sp::Derive( + _key.CascadeKey, kCascadeKeySize, + "AES-key", 7, + _keyAes, 32); + Aes_SetKey_Enc(AesKeys() + 4, _keyAes, 32); + memcpy(AesKeys(), _aesIv, 16); + + NHkdfBlake2sp::Derive( + _key.CascadeKey, kCascadeKeySize, + "XChaCha20-key", 13, + _keyXChaCha20, 32); + NXChaCha20::XHChaCha20Block_Core(_xcDerivedKey, _keyXChaCha20, _xcNonce); + + ComputePolyKey(); + _poly1305.SetKey(_polyKey); + if (_aadSize > 0) + _poly1305.UpdateAad(_aad, _aadSize); + + _xcBlockPos = 64; + _xcCounter = 1; + + _keyDerived = true; + _finalized = false; +} + +void CAXPBase::ComputePolyKey() +{ + Byte polyBlock[64]; + NXChaCha20::XChaCha20Block_Core(polyBlock, _xcDerivedKey, _xcNonce + 16, 0); + memcpy(_polyKey, polyBlock, kPolyKeySize); + Z7_memset_0_ARRAY(polyBlock); +} + +void CAXPBase::AesCtrXorData(Byte *data, UInt32 size) +{ + InitAesCtrFunc(); + if (size >= AES_BLOCK_SIZE) + { + UInt32 numBlocks = size >> 4; + s_AesCtrFunc(AesKeys(), data, numBlocks); + data += numBlocks << 4; + size -= numBlocks << 4; + } + if (size > 0) + { + Byte temp[16]; + memset(temp, 0, 16); + s_AesCtrFunc(AesKeys(), temp, 1); + for (UInt32 i = 0; i < size; i++) + data[i] ^= temp[i]; + Z7_memset_0_ARRAY(temp); + } +} + +void CAXPBase::XChaCha20XorData(Byte *data, UInt32 size) +{ + NXChaCha20::XChaCha20ProcessData(data, size, _xcDerivedKey, _xcNonce, _xcCounter, _xcBlock, _xcBlockPos); +} + +void CAXPBaseCoder::ProcessEnc(Byte *data, UInt32 size) +{ + if (!_keyDerived) + DeriveAXPKeys(); + + AesCtrXorData(data, size); + XChaCha20XorData(data, size); + _poly1305.Update(data, size); +} + +void CAXPBaseCoder::ProcessDec(Byte *data, UInt32 size) +{ + if (!_keyDerived) + DeriveAXPKeys(); + + _poly1305.Update(data, size); + XChaCha20XorData(data, size); + AesCtrXorData(data, size); +} + +Z7_COM7F_IMF(CAXPBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)) +{ + COM_TRY_BEGIN + + _key.Password.Wipe(); + _key.Password.CopyFrom(data, (size_t)size); + _keyDerived = false; + return S_OK; + + COM_TRY_END +} + +Z7_COM7F_IMF(CAXPBaseCoder::Init()) +{ + COM_TRY_BEGIN + + PrepareKey(); + _keyDerived = false; + _finalized = false; + _authOk = false; + _poly1305.Reset(); + return S_OK; + + COM_TRY_END +} + +Z7_COM7F_IMF2(UInt32, CAXPBaseCoder::Filter(Byte * /* data */, UInt32 size)) +{ + return size; +} + +#ifndef Z7_EXTRACT_ONLY + +CAXPEncoder::CAXPEncoder() +{ + _key.NumCyclesPower = 19; + _key.DerivMode = N7zKeyDerivation::kDeriv_Cascade; + _keyDerived = false; + _aadSize = 0; + _finalized = false; + _xcBlockPos = 64; + _xcCounter = 1; + _tagReady = false; + _propsWritten = false; + memset(_computedTag, 0, kTagSize); + Z7_memset_0_ARRAY(_aesIv); + Z7_memset_0_ARRAY(_xcNonce); +} + +Z7_COM7F_IMF(CAXPEncoder::ResetInitVector()) +{ + for (unsigned i = 0; i < sizeof(_aesIv); i++) + _aesIv[i] = 0; + for (unsigned i = 0; i < sizeof(_xcNonce); i++) + _xcNonce[i] = 0; + + MY_RAND_GEN(_key.Salt, N7zKeyDerivation::kCascadeSaltSize); + _key.SaltSize = N7zKeyDerivation::kCascadeSaltSize; + + MY_RAND_GEN(_aesIv, 16); + MY_RAND_GEN(_xcNonce, 24); + _keyDerived = false; + _finalized = false; + _xcBlockPos = 64; + _xcCounter = 1; + _poly1305.Reset(); + _tagReady = false; + _propsWritten = false; + memset(_computedTag, 0, kTagSize); + + _aadSize = 1; + _aad[0] = (Byte)(_key.NumCyclesPower + | (1 << 7) + | (1 << 6)); + + _aad[1] = (Byte)(((_key.SaltSize - 1) << 3) & 0xF8); + memcpy(_aad + 2, _key.Salt, _key.SaltSize); + _aadSize = 2 + _key.SaltSize; + memcpy(_aad + _aadSize, _aesIv, 16); + _aadSize += 16; + memcpy(_aad + _aadSize, _xcNonce, 24); + _aadSize += 24; + + return S_OK; +} + +Z7_COM7F_IMF2(UInt32, CAXPEncoder::Filter(Byte *data, UInt32 size)) +{ + if (size == 0) + return 0; + + ProcessEnc(data, size); + return size; +} + +Z7_COM7F_IMF(CAXPEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) +{ + Byte props[2 + sizeof(_key.Salt) + 24 + 16 + kTagSize]; + unsigned propsSize = 1; + + props[0] = (Byte)(_key.NumCyclesPower + | (1 << 7) + | (1 << 6)); + + props[1] = (Byte)(((_key.SaltSize - 1) << 3) & 0xF8); + memcpy(props + 2, _key.Salt, _key.SaltSize); + propsSize = 2 + _key.SaltSize; + memcpy(props + propsSize, _aesIv, 16); + propsSize += 16; + memcpy(props + propsSize, _xcNonce, 24); + propsSize += 24; + + if (!_tagReady) + { + if (!_keyDerived && _propsWritten) + DeriveAXPKeys(); + if (_finalized) + { + _tagReady = true; + } + else if (_keyDerived) + { + _poly1305.Final(_computedTag); + _finalized = true; + _tagReady = true; + } + else + { + memset(_computedTag, 0, kTagSize); + } + } + _propsWritten = true; + + memcpy(props + propsSize, _computedTag, kTagSize); + propsSize += kTagSize; + + return WriteStream(outStream, props, propsSize); +} + +#endif + +CAXPDecoder::CAXPDecoder() +{ + _key.NumCyclesPower = 19; + _key.DerivMode = N7zKeyDerivation::kDeriv_Cascade; + _keyDerived = false; + _finalized = false; + _authOk = false; + _aadSize = 0; + memset(_expectedTag, 0, kTagSize); + _xcBlockPos = 64; + _xcCounter = 1; + Z7_memset_0_ARRAY(_aesIv); + Z7_memset_0_ARRAY(_xcNonce); +} + +Z7_COM7F_IMF2(UInt32, CAXPDecoder::Filter(Byte *data, UInt32 size)) +{ + if (size == 0) + return 0; + + ProcessDec(data, size); + return size; +} + +Z7_COM7F_IMF(CAXPDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)) +{ + _key.ClearProps(); + _key.DerivMode = N7zKeyDerivation::kDeriv_Cascade; + + _keyDerived = false; + _finalized = false; + _authOk = false; + _poly1305.Reset(); + memset(_expectedTag, 0, kTagSize); + _xcBlockPos = 64; + _xcCounter = 1; + + for (unsigned i = 0; i < sizeof(_aesIv); i++) + _aesIv[i] = 0; + for (unsigned i = 0; i < sizeof(_xcNonce); i++) + _xcNonce[i] = 0; + + if (size == 0) + return S_OK; + + const unsigned b0 = data[0]; + _key.NumCyclesPower = b0 & 0x3F; + + const bool saltPresent = (b0 & 0x80) != 0; + const unsigned nonceType = (b0 >> 6) & 1; + + if (!saltPresent && nonceType == 0 && size == 1) + return S_OK; + if (size <= 1) + return E_INVALIDARG; + + const unsigned b1 = data[1]; + const unsigned saltSize = saltPresent ? (((b1 >> 3) & 0x1F) + 1) : 0; + const unsigned nonceSize = (nonceType == 0) ? 16 : 24; + + const unsigned minSize = 2 + saltSize + nonceSize + 16; + if (size < minSize) + return E_INVALIDARG; + + const unsigned tagSize = size - minSize; + if (tagSize != kTagSize && tagSize != 0) + return E_INVALIDARG; + + _key.SaltSize = saltSize; + data += 2; + for (unsigned i = 0; i < saltSize; i++) + _key.Salt[i] = *data++; + for (unsigned i = 0; i < 16; i++) + _aesIv[i] = *data++; + for (unsigned i = 0; i < nonceSize && i < 24; i++) + _xcNonce[i] = *data++; + + if (tagSize == kTagSize) + memcpy(_expectedTag, data, kTagSize); + + _aadSize = 1; + _aad[0] = (Byte)(_key.NumCyclesPower + | (saltPresent ? (1 << 7) : 0) + | (nonceType << 6)); + + if (saltPresent) + { + _aad[1] = (Byte)(((_key.SaltSize - 1) << 3) & 0xF8); + memcpy(_aad + 2, _key.Salt, _key.SaltSize); + _aadSize = 2 + _key.SaltSize; + memcpy(_aad + _aadSize, _aesIv, 16); + _aadSize += 16; + memcpy(_aad + _aadSize, _xcNonce, nonceSize); + _aadSize += nonceSize; + } + else + { + _aad[1] = 0; + _aadSize = 2; + memcpy(_aad + _aadSize, _aesIv, 16); + _aadSize += 16; + memcpy(_aad + _aadSize, _xcNonce, nonceSize); + _aadSize += nonceSize; + } + + return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX + || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL; +} + +Z7_COM7F_IMF(CAXPDecoder::CryptoAuthVerify(Int32 *result)) +{ + if (_authOk) + { + *result = 0; + return S_OK; + } + + if (!_keyDerived) + DeriveAXPKeys(); + + Byte computedTag[kTagSize]; + _poly1305.Final(computedTag); + _finalized = true; + + { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4746) +#endif + volatile Byte diff = 0; + for (unsigned i = 0; i < kTagSize; i++) + diff |= computedTag[i] ^ _expectedTag[i]; + *result = (diff == 0) ? 0 : 1; + _authOk = (diff == 0); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + } + + Z7_memset_0_ARRAY(computedTag); + + return S_OK; +} + +}} + +namespace NCrypto { +namespace NAXACascade { + +static CKeyInfoCache g_GlobalKeyCache(32); + +#ifndef Z7_ST + static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; + #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); +#else + #define MT_LOCK +#endif + +#ifdef MY_CPU_X86_OR_AMD64 +#define ASCON_USE_SSE2 (NAscon::g_SSE2Enabled) +#else +#define ASCON_USE_SSE2 false +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 +#define ASCON_USE_NEON (NAscon::g_NEONEnabled) +#else +#define ASCON_USE_NEON false +#endif + +CBase::CBase(): + _cachedKeys(16), + _keyDerived(false), + _aesKeys(AES_NUM_IVMRK_WORDS * sizeof(UInt32)), + _xcBlockPos(64), + _xcCounter(0) +{ + _key.DerivMode = N7zKeyDerivation::kDeriv_Cascade; + for (unsigned i = 0; i < sizeof(_nonce); i++) + _nonce[i] = 0; + Z7_memset_0_ARRAY(_keyAscon); + Z7_memset_0_ARRAY(_keyAes); + Z7_memset_0_ARRAY(_aesIv); + memset(_aesKeys, 0, AES_NUM_IVMRK_WORDS * sizeof(UInt32)); + Z7_memset_0_ARRAY(_keyXChaCha20); + Z7_memset_0_ARRAY(_xcNonce); + Z7_memset_0_ARRAY(_xcDerivedKey); + Z7_memset_0_ARRAY(_xcBlock); +} + +void CBase::PrepareKey() +{ + MT_LOCK + + bool finded = false; + if (!_cachedKeys.GetKey(_key)) + { + finded = g_GlobalKeyCache.GetKey(_key); + if (!finded) + _key.CalcKey(); + _cachedKeys.Add(_key); + } + if (!finded) + g_GlobalKeyCache.FindAndAdd(_key); + _keyDerived = false; +} + +void CBase::DeriveCascadeKeys() +{ + + NHkdfBlake2sp::Derive( + _key.CascadeKey, kCascadeKeySize, + "AES-key", 7, + _keyAes, 32); + Aes_SetKey_Enc(AesKeys() + 4, _keyAes, 32); + memcpy(AesKeys(), _aesIv, 16); + + NHkdfBlake2sp::Derive( + _key.CascadeKey, kCascadeKeySize, + "XChaCha20-key", 13, + _keyXChaCha20, 32); + NXChaCha20::XHChaCha20Block_Core(_xcDerivedKey, _keyXChaCha20, _xcNonce); + + NHkdfBlake2sp::Derive( + _key.CascadeKey, kCascadeKeySize, + "Ascon-key", 9, + _keyAscon, NAscon::kKeySize_Ascon); + + _xcBlockPos = 64; + _xcCounter = 0; + + _keyDerived = true; +} + +void CBase::AesCtrXorData(Byte *data, UInt32 size) +{ + InitAesCtrFunc(); + if (size >= AES_BLOCK_SIZE) + { + UInt32 numBlocks = size >> 4; + s_AesCtrFunc(AesKeys(), data, numBlocks); + data += numBlocks << 4; + size -= numBlocks << 4; + } + if (size > 0) + { + Byte temp[16]; + memset(temp, 0, 16); + s_AesCtrFunc(AesKeys(), temp, 1); + for (UInt32 i = 0; i < size; i++) + data[i] ^= temp[i]; + Z7_memset_0_ARRAY(temp); + } +} + +void CBase::XChaCha20XorData(Byte *data, UInt32 size) +{ + NXChaCha20::XChaCha20ProcessData(data, size, _xcDerivedKey, _xcNonce, _xcCounter, _xcBlock, _xcBlockPos); +} + +void CBaseCoder::InitState() +{ + Z7_memset_0_ARRAY(_state); + Z7_memset_0_ARRAY(_stateBuf); + _stateBufPos = 0; + _finalized = false; + _authOk = false; +} + +void CBaseCoder::ProcessAad(const Byte *aad, UInt64 aadLen) +{ + const UInt64 keyLo = GetUi64(_keyAscon); + const UInt64 keyHi = GetUi64(_keyAscon + 8); + const UInt64 nonceLo = GetUi64(_nonce); + const UInt64 nonceHi = GetUi64(_nonce + 8); + + _state[0] = NAscon::kIV_Ascon; + _state[1] = keyLo; + _state[2] = keyHi; + _state[3] = nonceLo; + _state[4] = nonceHi; + + NAscon::AsconP12(_state); + _state[3] ^= keyLo; + _state[4] ^= keyHi; + + if (aadLen > 0) + { + UInt64 remaining = aadLen; + const Byte *p = aad; + while (remaining >= NAscon::kRateSize) + { + _state[0] ^= GetUi64(p); + _state[1] ^= GetUi64(p + 8); + NAscon::AsconP8(_state); + p += NAscon::kRateSize; + remaining -= NAscon::kRateSize; + } + if (remaining >= 8) + { + _state[0] ^= GetUi64(p); + _state[1] ^= ((UInt64)0x01 << ((remaining - 8) * 8)); + if (remaining > 8) + { + UInt64 partial = 0; + memcpy(&partial, p + 8, (unsigned)(remaining - 8)); + _state[1] ^= partial; + } + } + else + { + _state[0] ^= ((UInt64)0x01 << (remaining * 8)); + if (remaining > 0) + { + UInt64 partial = 0; + memcpy(&partial, p, (unsigned)remaining); + _state[0] ^= partial; + } + } + NAscon::AsconP8(_state); + } + + _state[4] ^= (UInt64)0x80 << 56; +} + +void CBaseCoder::ProcessEnc(Byte *data, UInt32 size) +{ +#ifdef MY_CPU_X86_OR_AMD64 + NAscon::InitSIMD(); + const bool useSSE2 = ASCON_USE_SSE2; +#else + const bool useSSE2 = false; + (void)useSSE2; +#endif +#ifdef MY_CPU_ARM_OR_ARM64 + NAscon::InitSIMD(); + const bool useNEON = ASCON_USE_NEON; +#else + const bool useNEON = false; + (void)useNEON; +#endif + if (!_keyDerived) + { + DeriveCascadeKeys(); + ProcessAad(_aad, _aadSize); + } + + AesCtrXorData(data, size); + XChaCha20XorData(data, size); + + UInt32 remaining = size; + Byte *p = data; + + if (_stateBufPos > 0) + { + UInt32 avail = NAscon::kRateSize - _stateBufPos; + UInt32 toProcess = (remaining < avail) ? remaining : avail; + + XorBytes(p, _stateBuf + _stateBufPos, toProcess); + memcpy(_stateBuf + _stateBufPos, p, toProcess); + // 同步_stateBuf到_state,确保Finalize使用正确的状态计算Tag + // 与ProcessDec保持一致(参考ProcessDec第809行) + memcpy((Byte *)_state + _stateBufPos, _stateBuf + _stateBufPos, toProcess); + + _stateBufPos += toProcess; + p += toProcess; + remaining -= toProcess; + + if (_stateBufPos == NAscon::kRateSize) + { + _state[0] = GetUi64(_stateBuf); + _state[1] = GetUi64(_stateBuf + 8); + NAscon::AsconP8(_state); + _stateBufPos = 0; + } + } + + if (remaining >= NAscon::kRateSize) + { +#ifdef MY_CPU_SSE2 + if (useSSE2) + { + do { + NAscon::AsconEncBlock_SSE2(_state, p); + NAscon::AsconP8(_state); + p += NAscon::kRateSize; + remaining -= NAscon::kRateSize; + } while (remaining >= NAscon::kRateSize); + } + else +#endif +#ifdef MY_CPU_ARM_OR_ARM64 + if (useNEON) + { + do { + NAscon::AsconEncBlock_NEON(_state, p); + NAscon::AsconP8(_state); + p += NAscon::kRateSize; + remaining -= NAscon::kRateSize; + } while (remaining >= NAscon::kRateSize); + } + else +#endif + { + do { + _state[0] ^= GetUi64(p); + _state[1] ^= GetUi64(p + 8); + SetUi64(p, _state[0]); + SetUi64(p + 8, _state[1]); + NAscon::AsconP8(_state); + p += NAscon::kRateSize; + remaining -= NAscon::kRateSize; + } while (remaining >= NAscon::kRateSize); + } + } + + if (remaining > 0) + { + SetUi64(_stateBuf, _state[0]); + SetUi64(_stateBuf + 8, _state[1]); + XorBytes(p, _stateBuf, remaining); + memcpy(_stateBuf, p, remaining); + memcpy(_state, _stateBuf, remaining); + _stateBufPos = remaining; + } +} + +void CBaseCoder::ProcessDec(Byte *data, UInt32 size) +{ +#ifdef MY_CPU_X86_OR_AMD64 + NAscon::InitSIMD(); + const bool useSSE2 = ASCON_USE_SSE2; +#else + const bool useSSE2 = false; + (void)useSSE2; +#endif +#ifdef MY_CPU_ARM_OR_ARM64 + NAscon::InitSIMD(); + const bool useNEON = ASCON_USE_NEON; +#else + const bool useNEON = false; + (void)useNEON; +#endif + if (!_keyDerived) + { + DeriveCascadeKeys(); + ProcessAad(_aad, _aadSize); + } + + { + UInt32 remaining = size; + Byte *p = data; + + if (_stateBufPos > 0) + { + UInt32 avail = NAscon::kRateSize - _stateBufPos; + UInt32 toProcess = (remaining < avail) ? remaining : avail; + + { + UInt32 off = _stateBufPos; + UInt32 n = toProcess; + Byte *pd = p; +#ifdef MY_CPU_LE_UNALIGN_64 + while (n >= 8 && (off & 7) == 0) + { + UInt64 ct = GetUi64(pd); + SetUi64(pd, GetUi64(_stateBuf + off) ^ ct); + SetUi64(_stateBuf + off, ct); + pd += 8; off += 8; n -= 8; + } +#endif +#ifdef MY_CPU_LE_UNALIGN + while (n >= 4 && (off & 3) == 0) + { + UInt32 ct = GetUi32(pd); + SetUi32(pd, GetUi32(_stateBuf + off) ^ ct); + SetUi32(_stateBuf + off, ct); + pd += 4; off += 4; n -= 4; + } +#endif + while (n--) + { + const Byte c = *pd; + *pd = _stateBuf[off] ^ c; + _stateBuf[off] = c; + pd++; off++; + } + } + + memcpy((Byte *)_state + _stateBufPos, _stateBuf + _stateBufPos, toProcess); + + _stateBufPos += toProcess; + p += toProcess; + remaining -= toProcess; + + if (_stateBufPos == NAscon::kRateSize) + { + NAscon::AsconP8(_state); + _stateBufPos = 0; + } + } + + if (remaining >= NAscon::kRateSize) + { +#ifdef MY_CPU_SSE2 + if (useSSE2) + { + do { + NAscon::AsconDecBlock_SSE2(_state, p); + NAscon::AsconP8(_state); + p += NAscon::kRateSize; + remaining -= NAscon::kRateSize; + } while (remaining >= NAscon::kRateSize); + } + else +#endif +#ifdef MY_CPU_ARM_OR_ARM64 + if (useNEON) + { + do { + NAscon::AsconDecBlock_NEON(_state, p); + NAscon::AsconP8(_state); + p += NAscon::kRateSize; + remaining -= NAscon::kRateSize; + } while (remaining >= NAscon::kRateSize); + } + else +#endif + { + do { + UInt64 c0 = GetUi64(p); + UInt64 c1 = GetUi64(p + 8); + SetUi64(p, _state[0] ^ c0); + SetUi64(p + 8, _state[1] ^ c1); + _state[0] = c0; + _state[1] = c1; + NAscon::AsconP8(_state); + p += NAscon::kRateSize; + remaining -= NAscon::kRateSize; + } while (remaining >= NAscon::kRateSize); + } + } + + if (remaining > 0) + { + SetUi64(_stateBuf, _state[0]); + SetUi64(_stateBuf + 8, _state[1]); + + { + UInt32 n = remaining; + Byte *pd = p; + UInt32 off = 0; +#ifdef MY_CPU_LE_UNALIGN_64 + while (n >= 8) + { + UInt64 ct = GetUi64(pd); + SetUi64(pd, GetUi64(_stateBuf + off) ^ ct); + SetUi64(_stateBuf + off, ct); + pd += 8; off += 8; n -= 8; + } +#endif +#ifdef MY_CPU_LE_UNALIGN + while (n >= 4) + { + UInt32 ct = GetUi32(pd); + SetUi32(pd, GetUi32(_stateBuf + off) ^ ct); + SetUi32(_stateBuf + off, ct); + pd += 4; off += 4; n -= 4; + } +#endif + while (n--) + { + const Byte c = *pd; + *pd = _stateBuf[off] ^ c; + _stateBuf[off] = c; + pd++; off++; + } + } + + memcpy(_state, _stateBuf, remaining); + _stateBufPos = remaining; + } + } + + XChaCha20XorData(data, size); + AesCtrXorData(data, size); +} + +void CBaseCoder::Finalize(Byte *tag) +{ + if (!_finalized) + { + if (_stateBufPos > 0 && _stateBufPos < NAscon::kRateSize) + { + if (_stateBufPos < 8) + _state[0] ^= ((UInt64)0x01 << (_stateBufPos * 8)); + else + _state[1] ^= ((UInt64)0x01 << ((_stateBufPos - 8) * 8)); + } + else + { + _state[0] ^= ((UInt64)0x01); + } + + const UInt64 keyLo = GetUi64(_keyAscon); + const UInt64 keyHi = GetUi64(_keyAscon + 8); + + _state[2] ^= keyLo; + _state[3] ^= keyHi; + NAscon::AsconP12(_state); + _state[3] ^= keyLo; + _state[4] ^= keyHi; + + SetUi64(tag, _state[3]); + SetUi64(tag + 8, _state[4]); + + _finalized = true; + } +} + +Z7_COM7F_IMF(CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)) +{ + COM_TRY_BEGIN + + _key.Password.Wipe(); + _key.Password.CopyFrom(data, (size_t)size); + _keyDerived = false; + return S_OK; + + COM_TRY_END +} + +Z7_COM7F_IMF(CBaseCoder::Init()) +{ + COM_TRY_BEGIN + + PrepareKey(); + InitState(); + _keyDerived = false; + return S_OK; + + COM_TRY_END +} + +Z7_COM7F_IMF2(UInt32, CBaseCoder::Filter(Byte * /* data */, UInt32 size)) +{ + return size; +} + +#ifndef Z7_EXTRACT_ONLY + +Z7_COM7F_IMF(CEncoder::ResetInitVector()) +{ + for (unsigned i = 0; i < sizeof(_nonce); i++) + _nonce[i] = 0; + for (unsigned i = 0; i < sizeof(_aesIv); i++) + _aesIv[i] = 0; + for (unsigned i = 0; i < sizeof(_xcNonce); i++) + _xcNonce[i] = 0; + + MY_RAND_GEN(_key.Salt, N7zKeyDerivation::kCascadeSaltSize); + _key.SaltSize = N7zKeyDerivation::kCascadeSaltSize; + + MY_RAND_GEN(_nonce, NAscon::kNonceSize); + MY_RAND_GEN(_aesIv, 16); + MY_RAND_GEN(_xcNonce, 24); + _keyDerived = false; + _stateBufPos = 0; + _finalized = false; + _xcBlockPos = 64; + _xcCounter = 0; + _tagReady = false; + _propsWritten = false; + + const unsigned nonceType = (NAscon::kNonceSize > 16) ? 1 : 0; + + _aadSize = 1; + _aad[0] = (Byte)(_key.NumCyclesPower + | (1 << 7) + | (nonceType << 6)); + + _aad[1] = (Byte)(((_key.SaltSize - 1) << 3) & 0xF8); + memcpy(_aad + 2, _key.Salt, _key.SaltSize); + _aadSize = 2 + _key.SaltSize; + memcpy(_aad + _aadSize, _aesIv, 16); + _aadSize += 16; + memcpy(_aad + _aadSize, _xcNonce, 24); + _aadSize += 24; + memcpy(_aad + _aadSize, _nonce, NAscon::kNonceSize); + _aadSize += NAscon::kNonceSize; + + return S_OK; +} + +Z7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size)) +{ + if (size == 0) + return 0; + + ProcessEnc(data, size); + return size; +} + +CEncoder::CEncoder() +{ + _key.NumCyclesPower = 19; + _key.DerivMode = N7zKeyDerivation::kDeriv_Cascade; + _keyDerived = false; + _stateBufPos = 0; + _finalized = false; + _aadSize = 0; + _xcBlockPos = 64; + _xcCounter = 0; + _tagReady = false; + _propsWritten = false; + memset(_computedTag, 0, NAscon::kTagSize); + Z7_memset_0_ARRAY(_aesIv); + Z7_memset_0_ARRAY(_xcNonce); +} + +Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) +{ + Byte props[2 + sizeof(_key.Salt) + NAscon::kNonceSize + 16 + 24 + NAscon::kTagSize]; + unsigned propsSize = 1; + + const unsigned nonceType = (NAscon::kNonceSize > 16) ? 1 : 0; + + props[0] = (Byte)(_key.NumCyclesPower + | (1 << 7) + | (nonceType << 6)); + + props[1] = (Byte)(((_key.SaltSize - 1) << 3) & 0xF8); + memcpy(props + 2, _key.Salt, _key.SaltSize); + propsSize = 2 + _key.SaltSize; + memcpy(props + propsSize, _aesIv, 16); + propsSize += 16; + memcpy(props + propsSize, _xcNonce, 24); + propsSize += 24; + memcpy(props + propsSize, _nonce, NAscon::kNonceSize); + propsSize += NAscon::kNonceSize; + + if (!_tagReady) + { + if (!_keyDerived && _propsWritten) + { + DeriveCascadeKeys(); + ProcessAad(_aad, _aadSize); + } + if (_finalized) + { + _tagReady = true; + } + else if (_keyDerived) + { + Finalize(_computedTag); + _tagReady = true; + } + else + { + memset(_computedTag, 0, NAscon::kTagSize); + } + } + _propsWritten = true; + + memcpy(props + propsSize, _computedTag, NAscon::kTagSize); + propsSize += NAscon::kTagSize; + + return WriteStream(outStream, props, propsSize); +} + +#endif + +CDecoder::CDecoder() +{ + _key.NumCyclesPower = 19; + _key.DerivMode = N7zKeyDerivation::kDeriv_Cascade; + _keyDerived = false; + _stateBufPos = 0; + _finalized = false; + _authOk = false; + _aadSize = 0; + memset(_expectedTag, 0, NAscon::kTagSize); + _xcBlockPos = 64; + _xcCounter = 0; + Z7_memset_0_ARRAY(_aesIv); + Z7_memset_0_ARRAY(_xcNonce); +} + +Z7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size)) +{ + if (size == 0) + return 0; + + ProcessDec(data, size); + return size; +} + +Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)) +{ + _key.ClearProps(); + _key.DerivMode = N7zKeyDerivation::kDeriv_Cascade; + + _keyDerived = false; + _stateBufPos = 0; + _finalized = false; + _authOk = false; + memset(_expectedTag, 0, NAscon::kTagSize); + _xcBlockPos = 64; + _xcCounter = 0; + + for (unsigned i = 0; i < sizeof(_nonce); i++) + _nonce[i] = 0; + for (unsigned i = 0; i < sizeof(_aesIv); i++) + _aesIv[i] = 0; + for (unsigned i = 0; i < sizeof(_xcNonce); i++) + _xcNonce[i] = 0; + + if (size == 0) + return S_OK; + + const unsigned b0 = data[0]; + _key.NumCyclesPower = b0 & 0x3F; + + const bool saltPresent = (b0 & 0x80) != 0; + const unsigned nonceType = (b0 >> 6) & 1; + + if (!saltPresent && nonceType == 0 && size == 1) + return S_OK; + if (size <= 1) + return E_INVALIDARG; + + const unsigned b1 = data[1]; + const unsigned saltSize = saltPresent ? (((b1 >> 3) & 0x1F) + 1) : 0; + const unsigned nonceSize = (nonceType == 0) ? 16 : 24; + + const unsigned minSize = 2 + saltSize + nonceSize + 16 + 24; + if (size < minSize) + return E_INVALIDARG; + + const unsigned tagSize = size - minSize; + if (tagSize != NAscon::kTagSize && tagSize != 0) + return E_INVALIDARG; + + _key.SaltSize = saltSize; + data += 2; + for (unsigned i = 0; i < saltSize; i++) + _key.Salt[i] = *data++; + for (unsigned i = 0; i < 16; i++) + _aesIv[i] = *data++; + for (unsigned i = 0; i < 24; i++) + _xcNonce[i] = *data++; + for (unsigned i = 0; i < nonceSize && i < NAscon::kNonceSize; i++) + _nonce[i] = *data++; + + if (tagSize == NAscon::kTagSize) + memcpy(_expectedTag, data, NAscon::kTagSize); + + _aadSize = 1; + _aad[0] = (Byte)(_key.NumCyclesPower + | (saltPresent ? (1 << 7) : 0) + | (nonceType << 6)); + + if (saltPresent) + { + _aad[1] = (Byte)(((_key.SaltSize - 1) << 3) & 0xF8); + memcpy(_aad + 2, _key.Salt, _key.SaltSize); + _aadSize = 2 + _key.SaltSize; + memcpy(_aad + _aadSize, _aesIv, 16); + _aadSize += 16; + memcpy(_aad + _aadSize, _xcNonce, 24); + _aadSize += 24; + memcpy(_aad + _aadSize, _nonce, NAscon::kNonceSize); + _aadSize += NAscon::kNonceSize; + } + else + { + _aad[1] = 0; + _aadSize = 2; + memcpy(_aad + _aadSize, _aesIv, 16); + _aadSize += 16; + memcpy(_aad + _aadSize, _xcNonce, 24); + _aadSize += 24; + memcpy(_aad + _aadSize, _nonce, NAscon::kNonceSize); + _aadSize += NAscon::kNonceSize; + } + + return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX + || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL; +} + +Z7_COM7F_IMF(CDecoder::CryptoAuthVerify(Int32 *result)) +{ + if (_authOk) + { + *result = 0; + return S_OK; + } + + if (!_keyDerived) + { + DeriveCascadeKeys(); + ProcessAad(_aad, _aadSize); + } + + Byte computedTag[NAscon::kTagSize]; + Finalize(computedTag); + + { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable: 4746) +#endif + volatile Byte diff = 0; + for (unsigned i = 0; i < NAscon::kTagSize; i++) + diff |= computedTag[i] ^ _expectedTag[i]; + *result = (diff == 0) ? 0 : 1; + _authOk = (diff == 0); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + } + + Z7_memset_0_ARRAY(computedTag); + + return S_OK; +} + +}} diff --git a/CPP/7zip/Crypto/Cascade.h b/CPP/7zip/Crypto/Cascade.h new file mode 100644 index 00000000..50ab5b9c --- /dev/null +++ b/CPP/7zip/Crypto/Cascade.h @@ -0,0 +1,273 @@ +// Cascade.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_INC_CRYPTO_CASCADE_H +#define ZIP7_INC_CRYPTO_CASCADE_H + +#include "../../Common/MyCom.h" +#include "../../Common/MyBuffer2.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +#include "7zKeyDerivation.h" +#include "Ascon.h" + +#define AES_BLOCK_SIZE 16 +#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4) + +namespace NCrypto { +namespace NAXACascade { + +using CKeyInfo = N7zKeyDerivation::CKeyInfo; +using CKeyInfoCache = N7zKeyDerivation::CKeyInfoCache; + +using N7zKeyDerivation::kKeySize; +using N7zKeyDerivation::kCascadeKeySize; + +const unsigned k_NumCyclesPower_Supported_MAX = 24; + +static const unsigned kXcBlockSize = 64; + +class CBase +{ + CKeyInfoCache _cachedKeys; +protected: + CKeyInfo _key; + Byte _nonce[NAscon::kNonceSize]; + Byte _keyAscon[NAscon::kKeySize_Ascon]; + bool _keyDerived; + + Byte _keyAes[32]; + Byte _aesIv[16]; + CAlignedBuffer1 _aesKeys; + + Byte _keyXChaCha20[32]; + Byte _xcNonce[24]; + Byte _xcDerivedKey[32]; + Byte _xcBlock[64]; + unsigned _xcBlockPos; + UInt64 _xcCounter; + + UInt32 *AesKeys() { return (UInt32 *)(void *)(Byte *)_aesKeys; } + + void PrepareKey(); + void DeriveCascadeKeys(); + void AesCtrXorData(Byte *data, UInt32 size); + void XChaCha20XorData(Byte *data, UInt32 size); + CBase(); + ~CBase() + { + Z7_memset_0_ARRAY(_nonce); + Z7_memset_0_ARRAY(_keyAscon); + Z7_memset_0_ARRAY(_keyAes); + Z7_memset_0_ARRAY(_aesIv); + memset(_aesKeys, 0, AES_NUM_IVMRK_WORDS * sizeof(UInt32)); + Z7_memset_0_ARRAY(_keyXChaCha20); + Z7_memset_0_ARRAY(_xcNonce); + Z7_memset_0_ARRAY(_xcDerivedKey); + Z7_memset_0_ARRAY(_xcBlock); + } +}; + +class CBaseCoder: + public ICompressFilter, + public ICryptoSetPassword, + public CMyUnknownImp, + public CBase +{ + Z7_IFACE_COM7_IMP_NONFINAL(ICompressFilter) + Z7_IFACE_COM7_IMP_NONFINAL(ICryptoSetPassword) +protected: + virtual ~CBaseCoder() + { + Z7_memset_0_ARRAY(_aad); + Z7_memset_0_ARRAY(_state); + } + + Byte _aad[2 + 32 + NAscon::kNonceSize + 16 + 24]; + unsigned _aadSize; + + UInt64 _state[5]; + Byte _stateBuf[NAscon::kRateSize]; + unsigned _stateBufPos; + bool _finalized; + bool _authOk; + + void InitState(); + void ProcessAad(const Byte *aad, UInt64 aadLen); + void ProcessEnc(Byte *data, UInt32 size); + void ProcessDec(Byte *data, UInt32 size); + void Finalize(Byte *tag); +}; + +#ifndef Z7_EXTRACT_ONLY + +class CEncoder Z7_final: + public CBaseCoder, + public ICompressWriteCoderProperties, + public ICryptoResetInitVector +{ + Z7_COM_UNKNOWN_IMP_4( + ICompressFilter, + ICryptoSetPassword, + ICompressWriteCoderProperties, + ICryptoResetInitVector) + Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties) + Z7_IFACE_COM7_IMP(ICryptoResetInitVector) + + Byte _computedTag[NAscon::kTagSize]; + bool _tagReady; + bool _propsWritten; + Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) +public: + CEncoder(); +}; + +#endif + +class CDecoder Z7_final: + public CBaseCoder, + public ICompressSetDecoderProperties2, + public ICryptoAuthVerify +{ + Z7_COM_UNKNOWN_IMP_4( + ICompressFilter, + ICryptoSetPassword, + ICompressSetDecoderProperties2, + ICryptoAuthVerify) + Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) + Z7_IFACE_COM7_IMP(ICryptoAuthVerify) + + Byte _expectedTag[NAscon::kTagSize]; + Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) +public: + CDecoder(); +}; + +}} + +#include "XChaCha20Poly1305.h" + +namespace NCrypto { +namespace NAXPCascade { + +using NAXACascade::CKeyInfo; +using NAXACascade::CKeyInfoCache; +using NAXACascade::k_NumCyclesPower_Supported_MAX; +using NAXACascade::kCascadeKeySize; +using NAXACascade::kXcBlockSize; + +using NXChaCha20Poly1305::kTagSize; +using NXChaCha20Poly1305::kPolyKeySize; + +class CAXPBase +{ + CKeyInfoCache _cachedKeys; +protected: + CKeyInfo _key; + bool _keyDerived; + + Byte _keyAes[32]; + Byte _aesIv[16]; + CAlignedBuffer1 _aesKeys; + + Byte _keyXChaCha20[32]; + Byte _xcNonce[24]; + Byte _xcDerivedKey[32]; + Byte _xcBlock[64]; + unsigned _xcBlockPos; + UInt64 _xcCounter; + + Byte _polyKey[kPolyKeySize]; + NXChaCha20Poly1305::CPoly1305 _poly1305; + Byte _aad[2 + 32 + 24 + 16]; + unsigned _aadSize; + bool _finalized; + bool _authOk; + + UInt32 *AesKeys() { return (UInt32 *)(void *)(Byte *)_aesKeys; } + + void PrepareKey(); + void DeriveAXPKeys(); + void ComputePolyKey(); + void AesCtrXorData(Byte *data, UInt32 size); + void XChaCha20XorData(Byte *data, UInt32 size); + + CAXPBase(); + ~CAXPBase() + { + Z7_memset_0_ARRAY(_keyAes); + Z7_memset_0_ARRAY(_aesIv); + memset(_aesKeys, 0, AES_NUM_IVMRK_WORDS * sizeof(UInt32)); + Z7_memset_0_ARRAY(_keyXChaCha20); + Z7_memset_0_ARRAY(_xcNonce); + Z7_memset_0_ARRAY(_xcDerivedKey); + Z7_memset_0_ARRAY(_xcBlock); + Z7_memset_0_ARRAY(_polyKey); + Z7_memset_0_ARRAY(_aad); + } +}; + +class CAXPBaseCoder: + public ICompressFilter, + public ICryptoSetPassword, + public CMyUnknownImp, + public CAXPBase +{ + Z7_IFACE_COM7_IMP_NONFINAL(ICompressFilter) + Z7_IFACE_COM7_IMP_NONFINAL(ICryptoSetPassword) +protected: + virtual ~CAXPBaseCoder() {} + void ProcessEnc(Byte *data, UInt32 size); + void ProcessDec(Byte *data, UInt32 size); +}; + +#ifndef Z7_EXTRACT_ONLY + +class CAXPEncoder Z7_final: + public CAXPBaseCoder, + public ICompressWriteCoderProperties, + public ICryptoResetInitVector +{ + Z7_COM_UNKNOWN_IMP_4( + ICompressFilter, + ICryptoSetPassword, + ICompressWriteCoderProperties, + ICryptoResetInitVector) + Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties) + Z7_IFACE_COM7_IMP(ICryptoResetInitVector) + + Byte _computedTag[kTagSize]; + bool _tagReady; + bool _propsWritten; + Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) +public: + CAXPEncoder(); +}; + +#endif + +class CAXPDecoder Z7_final: + public CAXPBaseCoder, + public ICompressSetDecoderProperties2, + public ICryptoAuthVerify +{ + Z7_COM_UNKNOWN_IMP_4( + ICompressFilter, + ICryptoSetPassword, + ICompressSetDecoderProperties2, + ICryptoAuthVerify) + Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) + Z7_IFACE_COM7_IMP(ICryptoAuthVerify) + + Byte _expectedTag[kTagSize]; + Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) +public: + CAXPDecoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/CascadeRegister.cpp b/CPP/7zip/Crypto/CascadeRegister.cpp new file mode 100644 index 00000000..bdc5c273 --- /dev/null +++ b/CPP/7zip/Crypto/CascadeRegister.cpp @@ -0,0 +1,29 @@ +// CascadeRegister.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "Cascade.h" + +namespace NCrypto { +namespace NAXPCascade { + +REGISTER_FILTER_E(AXP, + CAXPDecoder, + CAXPEncoder, + 0x6F10704, "AES+XChaCha20-Poly1305") + +}} + +namespace NCrypto { +namespace NAXACascade { + +REGISTER_FILTER_E(AXA, + CDecoder, + CEncoder, + 0x6F10705, "AES+XChaCha20+Ascon") + +}} diff --git a/CPP/7zip/Crypto/ChaCha20Simd.h b/CPP/7zip/Crypto/ChaCha20Simd.h new file mode 100644 index 00000000..12efe072 --- /dev/null +++ b/CPP/7zip/Crypto/ChaCha20Simd.h @@ -0,0 +1,731 @@ +// ChaCha20Simd.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_CRYPTO_CHACHA20_SIMD_H +#define ZIP7_CRYPTO_CHACHA20_SIMD_H + +#ifdef MY_CPU_X86_OR_AMD64 +#if defined(_MSC_VER) +#include +#elif defined(__GNUC__) +#include +#endif +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 +#include +#endif + +static const Byte kSigma[16] = { + 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k' +}; + +#ifdef MY_CPU_X86_OR_AMD64 + +#ifdef MY_CPU_SSE2 + +namespace { + +template +Z7_FORCE_INLINE __m128i RotateLeft_SSE2(const __m128i val) +{ + return _mm_or_si128(_mm_slli_epi32(val, R), _mm_srli_epi32(val, 32 - R)); +} + +template <> +Z7_FORCE_INLINE __m128i RotateLeft_SSE2<8>(const __m128i val) +{ +#ifdef __SSSE3__ + const __m128i mask = _mm_set_epi8(14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3); + return _mm_shuffle_epi8(val, mask); +#else + return _mm_or_si128(_mm_slli_epi32(val, 8), _mm_srli_epi32(val, 24)); +#endif +} + +template <> +Z7_FORCE_INLINE __m128i RotateLeft_SSE2<16>(const __m128i val) +{ +#ifdef __SSSE3__ + const __m128i mask = _mm_set_epi8(13,12,15,14, 9,8,11,10, 5,4,7,6, 1,0,3,2); + return _mm_shuffle_epi8(val, mask); +#else + return _mm_or_si128(_mm_slli_epi32(val, 16), _mm_srli_epi32(val, 16)); +#endif +} + +#define SSE2_QUARTERROUND(a, b, c, d) \ + a = _mm_add_epi32(a, b); \ + d = _mm_xor_si128(d, a); \ + d = RotateLeft_SSE2<16>(d); \ + c = _mm_add_epi32(c, d); \ + b = _mm_xor_si128(b, c); \ + b = RotateLeft_SSE2<12>(b); \ + a = _mm_add_epi32(a, b); \ + d = _mm_xor_si128(d, a); \ + d = RotateLeft_SSE2<8>(d); \ + c = _mm_add_epi32(c, d); \ + b = _mm_xor_si128(b, c); \ + b = RotateLeft_SSE2<7>(b); + +Z7_NO_INLINE void ChaCha20_OperateKeystream_SSE2( + const UInt32 *state, + const Byte *input, + Byte *output) +{ + const __m128i state0 = _mm_loadu_si128((const __m128i *)(state + 0)); + const __m128i state1 = _mm_loadu_si128((const __m128i *)(state + 4)); + const __m128i state2 = _mm_loadu_si128((const __m128i *)(state + 8)); + const __m128i state3 = _mm_loadu_si128((const __m128i *)(state + 12)); + + __m128i r0_0 = state0; + __m128i r0_1 = state1; + __m128i r0_2 = state2; + __m128i r0_3 = state3; + + __m128i r1_0 = state0; + __m128i r1_1 = state1; + __m128i r1_2 = state2; + __m128i r1_3 = _mm_add_epi64(state3, _mm_set_epi32(0, 0, 0, 1)); + + __m128i r2_0 = state0; + __m128i r2_1 = state1; + __m128i r2_2 = state2; + __m128i r2_3 = _mm_add_epi64(state3, _mm_set_epi32(0, 0, 0, 2)); + + __m128i r3_0 = state0; + __m128i r3_1 = state1; + __m128i r3_2 = state2; + __m128i r3_3 = _mm_add_epi64(state3, _mm_set_epi32(0, 0, 0, 3)); + + for (int i = 0; i < 10; i++) + { + SSE2_QUARTERROUND(r0_0, r0_1, r0_2, r0_3); + SSE2_QUARTERROUND(r1_0, r1_1, r1_2, r1_3); + SSE2_QUARTERROUND(r2_0, r2_1, r2_2, r2_3); + SSE2_QUARTERROUND(r3_0, r3_1, r3_2, r3_3); + + r0_1 = _mm_shuffle_epi32(r0_1, _MM_SHUFFLE(0, 3, 2, 1)); + r0_2 = _mm_shuffle_epi32(r0_2, _MM_SHUFFLE(1, 0, 3, 2)); + r0_3 = _mm_shuffle_epi32(r0_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r1_1 = _mm_shuffle_epi32(r1_1, _MM_SHUFFLE(0, 3, 2, 1)); + r1_2 = _mm_shuffle_epi32(r1_2, _MM_SHUFFLE(1, 0, 3, 2)); + r1_3 = _mm_shuffle_epi32(r1_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r2_1 = _mm_shuffle_epi32(r2_1, _MM_SHUFFLE(0, 3, 2, 1)); + r2_2 = _mm_shuffle_epi32(r2_2, _MM_SHUFFLE(1, 0, 3, 2)); + r2_3 = _mm_shuffle_epi32(r2_3, _MM_SHUFFLE(2, 1, 0, 3)); + + r3_1 = _mm_shuffle_epi32(r3_1, _MM_SHUFFLE(0, 3, 2, 1)); + r3_2 = _mm_shuffle_epi32(r3_2, _MM_SHUFFLE(1, 0, 3, 2)); + r3_3 = _mm_shuffle_epi32(r3_3, _MM_SHUFFLE(2, 1, 0, 3)); + + SSE2_QUARTERROUND(r0_0, r0_1, r0_2, r0_3); + SSE2_QUARTERROUND(r1_0, r1_1, r1_2, r1_3); + SSE2_QUARTERROUND(r2_0, r2_1, r2_2, r2_3); + SSE2_QUARTERROUND(r3_0, r3_1, r3_2, r3_3); + + r0_1 = _mm_shuffle_epi32(r0_1, _MM_SHUFFLE(2, 1, 0, 3)); + r0_2 = _mm_shuffle_epi32(r0_2, _MM_SHUFFLE(1, 0, 3, 2)); + r0_3 = _mm_shuffle_epi32(r0_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r1_1 = _mm_shuffle_epi32(r1_1, _MM_SHUFFLE(2, 1, 0, 3)); + r1_2 = _mm_shuffle_epi32(r1_2, _MM_SHUFFLE(1, 0, 3, 2)); + r1_3 = _mm_shuffle_epi32(r1_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r2_1 = _mm_shuffle_epi32(r2_1, _MM_SHUFFLE(2, 1, 0, 3)); + r2_2 = _mm_shuffle_epi32(r2_2, _MM_SHUFFLE(1, 0, 3, 2)); + r2_3 = _mm_shuffle_epi32(r2_3, _MM_SHUFFLE(0, 3, 2, 1)); + + r3_1 = _mm_shuffle_epi32(r3_1, _MM_SHUFFLE(2, 1, 0, 3)); + r3_2 = _mm_shuffle_epi32(r3_2, _MM_SHUFFLE(1, 0, 3, 2)); + r3_3 = _mm_shuffle_epi32(r3_3, _MM_SHUFFLE(0, 3, 2, 1)); + } + + r0_0 = _mm_add_epi32(r0_0, state0); + r0_1 = _mm_add_epi32(r0_1, state1); + r0_2 = _mm_add_epi32(r0_2, state2); + r0_3 = _mm_add_epi32(r0_3, state3); + + r1_0 = _mm_add_epi32(r1_0, state0); + r1_1 = _mm_add_epi32(r1_1, state1); + r1_2 = _mm_add_epi32(r1_2, state2); + r1_3 = _mm_add_epi32(r1_3, state3); + r1_3 = _mm_add_epi64(r1_3, _mm_set_epi32(0, 0, 0, 1)); + + r2_0 = _mm_add_epi32(r2_0, state0); + r2_1 = _mm_add_epi32(r2_1, state1); + r2_2 = _mm_add_epi32(r2_2, state2); + r2_3 = _mm_add_epi32(r2_3, state3); + r2_3 = _mm_add_epi64(r2_3, _mm_set_epi32(0, 0, 0, 2)); + + r3_0 = _mm_add_epi32(r3_0, state0); + r3_1 = _mm_add_epi32(r3_1, state1); + r3_2 = _mm_add_epi32(r3_2, state2); + r3_3 = _mm_add_epi32(r3_3, state3); + r3_3 = _mm_add_epi64(r3_3, _mm_set_epi32(0, 0, 0, 3)); + + if (input) + { + r0_0 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 0*16)), r0_0); + r0_1 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 1*16)), r0_1); + r0_2 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 2*16)), r0_2); + r0_3 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 3*16)), r0_3); + } + + _mm_storeu_si128((__m128i *)(output + 0*16), r0_0); + _mm_storeu_si128((__m128i *)(output + 1*16), r0_1); + _mm_storeu_si128((__m128i *)(output + 2*16), r0_2); + _mm_storeu_si128((__m128i *)(output + 3*16), r0_3); + + if (input) + { + r1_0 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 4*16)), r1_0); + r1_1 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 5*16)), r1_1); + r1_2 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 6*16)), r1_2); + r1_3 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 7*16)), r1_3); + } + + _mm_storeu_si128((__m128i *)(output + 4*16), r1_0); + _mm_storeu_si128((__m128i *)(output + 5*16), r1_1); + _mm_storeu_si128((__m128i *)(output + 6*16), r1_2); + _mm_storeu_si128((__m128i *)(output + 7*16), r1_3); + + if (input) + { + r2_0 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 8*16)), r2_0); + r2_1 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 9*16)), r2_1); + r2_2 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 10*16)), r2_2); + r2_3 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 11*16)), r2_3); + } + + _mm_storeu_si128((__m128i *)(output + 8*16), r2_0); + _mm_storeu_si128((__m128i *)(output + 9*16), r2_1); + _mm_storeu_si128((__m128i *)(output + 10*16), r2_2); + _mm_storeu_si128((__m128i *)(output + 11*16), r2_3); + + if (input) + { + r3_0 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 12*16)), r3_0); + r3_1 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 13*16)), r3_1); + r3_2 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 14*16)), r3_2); + r3_3 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)(input + 15*16)), r3_3); + } + + _mm_storeu_si128((__m128i *)(output + 12*16), r3_0); + _mm_storeu_si128((__m128i *)(output + 13*16), r3_1); + _mm_storeu_si128((__m128i *)(output + 14*16), r3_2); + _mm_storeu_si128((__m128i *)(output + 15*16), r3_3); +} + +#ifdef MY_CPU_AMD64 + +#if defined(__GNUC__) || defined(__clang__) +#define Z7_AVX2_TARGET_ATTR __attribute__((target("avx2"))) +#else +#define Z7_AVX2_TARGET_ATTR +#endif + +template +Z7_AVX2_TARGET_ATTR Z7_FORCE_INLINE __m256i RotateLeft_AVX2(const __m256i val) +{ + return _mm256_or_si256(_mm256_slli_epi32(val, R), _mm256_srli_epi32(val, 32 - R)); +} + +template <> +Z7_AVX2_TARGET_ATTR Z7_FORCE_INLINE __m256i RotateLeft_AVX2<8>(const __m256i val) +{ + const __m256i mask = _mm256_set_epi8( + 14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3, + 14,13,12,15, 10,9,8,11, 6,5,4,7, 2,1,0,3); + return _mm256_shuffle_epi8(val, mask); +} + +template <> +Z7_AVX2_TARGET_ATTR Z7_FORCE_INLINE __m256i RotateLeft_AVX2<16>(const __m256i val) +{ + const __m256i mask = _mm256_set_epi8( + 13,12,15,14, 9,8,11,10, 5,4,7,6, 1,0,3,2, + 13,12,15,14, 9,8,11,10, 5,4,7,6, 1,0,3,2); + return _mm256_shuffle_epi8(val, mask); +} + +#define AVX2_QUARTERROUND(a, b, c, d) \ + a = _mm256_add_epi32(a, b); \ + d = _mm256_xor_si256(d, a); \ + d = RotateLeft_AVX2<16>(d); \ + c = _mm256_add_epi32(c, d); \ + b = _mm256_xor_si256(b, c); \ + b = RotateLeft_AVX2<12>(b); \ + a = _mm256_add_epi32(a, b); \ + d = _mm256_xor_si256(d, a); \ + d = RotateLeft_AVX2<8>(d); \ + c = _mm256_add_epi32(c, d); \ + b = _mm256_xor_si256(b, c); \ + b = RotateLeft_AVX2<7>(b); + +Z7_AVX2_TARGET_ATTR Z7_NO_INLINE void ChaCha20_OperateKeystream_AVX2( + const UInt32 *state, + const Byte *input, + Byte *output) +{ + const __m256i state0 = _mm256_broadcastsi128_si256(_mm_loadu_si128((const __m128i *)(state + 0))); + const __m256i state1 = _mm256_broadcastsi128_si256(_mm_loadu_si128((const __m128i *)(state + 4))); + const __m256i state2 = _mm256_broadcastsi128_si256(_mm_loadu_si128((const __m128i *)(state + 8))); + const __m256i state3 = _mm256_broadcastsi128_si256(_mm_loadu_si128((const __m128i *)(state + 12))); + + const UInt32 C = 0xFFFFFFFFu - state[12]; + const __m256i CTR0 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, C < 4, 4); + const __m256i CTR1 = _mm256_set_epi32(0, 0, C < 1, 1, 0, 0, C < 5, 5); + const __m256i CTR2 = _mm256_set_epi32(0, 0, C < 2, 2, 0, 0, C < 6, 6); + const __m256i CTR3 = _mm256_set_epi32(0, 0, C < 3, 3, 0, 0, C < 7, 7); + + __m256i X0_0 = state0; + __m256i X0_1 = state1; + __m256i X0_2 = state2; + __m256i X0_3 = _mm256_add_epi32(state3, CTR0); + + __m256i X1_0 = state0; + __m256i X1_1 = state1; + __m256i X1_2 = state2; + __m256i X1_3 = _mm256_add_epi32(state3, CTR1); + + __m256i X2_0 = state0; + __m256i X2_1 = state1; + __m256i X2_2 = state2; + __m256i X2_3 = _mm256_add_epi32(state3, CTR2); + + __m256i X3_0 = state0; + __m256i X3_1 = state1; + __m256i X3_2 = state2; + __m256i X3_3 = _mm256_add_epi32(state3, CTR3); + + for (int i = 0; i < 10; i++) + { + AVX2_QUARTERROUND(X0_0, X0_1, X0_2, X0_3); + AVX2_QUARTERROUND(X1_0, X1_1, X1_2, X1_3); + AVX2_QUARTERROUND(X2_0, X2_1, X2_2, X2_3); + AVX2_QUARTERROUND(X3_0, X3_1, X3_2, X3_3); + + X0_1 = _mm256_shuffle_epi32(X0_1, _MM_SHUFFLE(0, 3, 2, 1)); + X0_2 = _mm256_shuffle_epi32(X0_2, _MM_SHUFFLE(1, 0, 3, 2)); + X0_3 = _mm256_shuffle_epi32(X0_3, _MM_SHUFFLE(2, 1, 0, 3)); + + X1_1 = _mm256_shuffle_epi32(X1_1, _MM_SHUFFLE(0, 3, 2, 1)); + X1_2 = _mm256_shuffle_epi32(X1_2, _MM_SHUFFLE(1, 0, 3, 2)); + X1_3 = _mm256_shuffle_epi32(X1_3, _MM_SHUFFLE(2, 1, 0, 3)); + + X2_1 = _mm256_shuffle_epi32(X2_1, _MM_SHUFFLE(0, 3, 2, 1)); + X2_2 = _mm256_shuffle_epi32(X2_2, _MM_SHUFFLE(1, 0, 3, 2)); + X2_3 = _mm256_shuffle_epi32(X2_3, _MM_SHUFFLE(2, 1, 0, 3)); + + X3_1 = _mm256_shuffle_epi32(X3_1, _MM_SHUFFLE(0, 3, 2, 1)); + X3_2 = _mm256_shuffle_epi32(X3_2, _MM_SHUFFLE(1, 0, 3, 2)); + X3_3 = _mm256_shuffle_epi32(X3_3, _MM_SHUFFLE(2, 1, 0, 3)); + + AVX2_QUARTERROUND(X0_0, X0_1, X0_2, X0_3); + AVX2_QUARTERROUND(X1_0, X1_1, X1_2, X1_3); + AVX2_QUARTERROUND(X2_0, X2_1, X2_2, X2_3); + AVX2_QUARTERROUND(X3_0, X3_1, X3_2, X3_3); + + X0_1 = _mm256_shuffle_epi32(X0_1, _MM_SHUFFLE(2, 1, 0, 3)); + X0_2 = _mm256_shuffle_epi32(X0_2, _MM_SHUFFLE(1, 0, 3, 2)); + X0_3 = _mm256_shuffle_epi32(X0_3, _MM_SHUFFLE(0, 3, 2, 1)); + + X1_1 = _mm256_shuffle_epi32(X1_1, _MM_SHUFFLE(2, 1, 0, 3)); + X1_2 = _mm256_shuffle_epi32(X1_2, _MM_SHUFFLE(1, 0, 3, 2)); + X1_3 = _mm256_shuffle_epi32(X1_3, _MM_SHUFFLE(0, 3, 2, 1)); + + X2_1 = _mm256_shuffle_epi32(X2_1, _MM_SHUFFLE(2, 1, 0, 3)); + X2_2 = _mm256_shuffle_epi32(X2_2, _MM_SHUFFLE(1, 0, 3, 2)); + X2_3 = _mm256_shuffle_epi32(X2_3, _MM_SHUFFLE(0, 3, 2, 1)); + + X3_1 = _mm256_shuffle_epi32(X3_1, _MM_SHUFFLE(2, 1, 0, 3)); + X3_2 = _mm256_shuffle_epi32(X3_2, _MM_SHUFFLE(1, 0, 3, 2)); + X3_3 = _mm256_shuffle_epi32(X3_3, _MM_SHUFFLE(0, 3, 2, 1)); + } + + X0_0 = _mm256_add_epi32(X0_0, state0); + X0_1 = _mm256_add_epi32(X0_1, state1); + X0_2 = _mm256_add_epi32(X0_2, state2); + X0_3 = _mm256_add_epi32(X0_3, state3); + X0_3 = _mm256_add_epi32(X0_3, CTR0); + + X1_0 = _mm256_add_epi32(X1_0, state0); + X1_1 = _mm256_add_epi32(X1_1, state1); + X1_2 = _mm256_add_epi32(X1_2, state2); + X1_3 = _mm256_add_epi32(X1_3, state3); + X1_3 = _mm256_add_epi32(X1_3, CTR1); + + X2_0 = _mm256_add_epi32(X2_0, state0); + X2_1 = _mm256_add_epi32(X2_1, state1); + X2_2 = _mm256_add_epi32(X2_2, state2); + X2_3 = _mm256_add_epi32(X2_3, state3); + X2_3 = _mm256_add_epi32(X2_3, CTR2); + + X3_0 = _mm256_add_epi32(X3_0, state0); + X3_1 = _mm256_add_epi32(X3_1, state1); + X3_2 = _mm256_add_epi32(X3_2, state2); + X3_3 = _mm256_add_epi32(X3_3, state3); + X3_3 = _mm256_add_epi32(X3_3, CTR3); + + if (input) + { + _mm256_storeu_si256((__m256i *)(output + 0*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X0_0, X0_1, 1 + (3 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 0*32)))); + _mm256_storeu_si256((__m256i *)(output + 1*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X0_2, X0_3, 1 + (3 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 1*32)))); + _mm256_storeu_si256((__m256i *)(output + 2*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X1_0, X1_1, 1 + (3 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 2*32)))); + _mm256_storeu_si256((__m256i *)(output + 3*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X1_2, X1_3, 1 + (3 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 3*32)))); + } + else + { + _mm256_storeu_si256((__m256i *)(output + 0*32), + _mm256_permute2x128_si256(X0_0, X0_1, 1 + (3 << 4))); + _mm256_storeu_si256((__m256i *)(output + 1*32), + _mm256_permute2x128_si256(X0_2, X0_3, 1 + (3 << 4))); + _mm256_storeu_si256((__m256i *)(output + 2*32), + _mm256_permute2x128_si256(X1_0, X1_1, 1 + (3 << 4))); + _mm256_storeu_si256((__m256i *)(output + 3*32), + _mm256_permute2x128_si256(X1_2, X1_3, 1 + (3 << 4))); + } + + if (input) + { + _mm256_storeu_si256((__m256i *)(output + 4*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X2_0, X2_1, 1 + (3 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 4*32)))); + _mm256_storeu_si256((__m256i *)(output + 5*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X2_2, X2_3, 1 + (3 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 5*32)))); + _mm256_storeu_si256((__m256i *)(output + 6*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X3_0, X3_1, 1 + (3 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 6*32)))); + _mm256_storeu_si256((__m256i *)(output + 7*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X3_2, X3_3, 1 + (3 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 7*32)))); + } + else + { + _mm256_storeu_si256((__m256i *)(output + 4*32), + _mm256_permute2x128_si256(X2_0, X2_1, 1 + (3 << 4))); + _mm256_storeu_si256((__m256i *)(output + 5*32), + _mm256_permute2x128_si256(X2_2, X2_3, 1 + (3 << 4))); + _mm256_storeu_si256((__m256i *)(output + 6*32), + _mm256_permute2x128_si256(X3_0, X3_1, 1 + (3 << 4))); + _mm256_storeu_si256((__m256i *)(output + 7*32), + _mm256_permute2x128_si256(X3_2, X3_3, 1 + (3 << 4))); + } + + if (input) + { + _mm256_storeu_si256((__m256i *)(output + 8*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X0_0, X0_1, 0 + (2 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 8*32)))); + _mm256_storeu_si256((__m256i *)(output + 9*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X0_2, X0_3, 0 + (2 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 9*32)))); + _mm256_storeu_si256((__m256i *)(output + 10*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X1_0, X1_1, 0 + (2 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 10*32)))); + _mm256_storeu_si256((__m256i *)(output + 11*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X1_2, X1_3, 0 + (2 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 11*32)))); + } + else + { + _mm256_storeu_si256((__m256i *)(output + 8*32), + _mm256_permute2x128_si256(X0_0, X0_1, 0 + (2 << 4))); + _mm256_storeu_si256((__m256i *)(output + 9*32), + _mm256_permute2x128_si256(X0_2, X0_3, 0 + (2 << 4))); + _mm256_storeu_si256((__m256i *)(output + 10*32), + _mm256_permute2x128_si256(X1_0, X1_1, 0 + (2 << 4))); + _mm256_storeu_si256((__m256i *)(output + 11*32), + _mm256_permute2x128_si256(X1_2, X1_3, 0 + (2 << 4))); + } + + if (input) + { + _mm256_storeu_si256((__m256i *)(output + 12*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X2_0, X2_1, 0 + (2 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 12*32)))); + _mm256_storeu_si256((__m256i *)(output + 13*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X2_2, X2_3, 0 + (2 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 13*32)))); + _mm256_storeu_si256((__m256i *)(output + 14*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X3_0, X3_1, 0 + (2 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 14*32)))); + _mm256_storeu_si256((__m256i *)(output + 15*32), + _mm256_xor_si256(_mm256_permute2x128_si256(X3_2, X3_3, 0 + (2 << 4)), + _mm256_loadu_si256((const __m256i *)(input + 15*32)))); + } + else + { + _mm256_storeu_si256((__m256i *)(output + 12*32), + _mm256_permute2x128_si256(X2_0, X2_1, 0 + (2 << 4))); + _mm256_storeu_si256((__m256i *)(output + 13*32), + _mm256_permute2x128_si256(X2_2, X2_3, 0 + (2 << 4))); + _mm256_storeu_si256((__m256i *)(output + 14*32), + _mm256_permute2x128_si256(X3_0, X3_1, 0 + (2 << 4))); + _mm256_storeu_si256((__m256i *)(output + 15*32), + _mm256_permute2x128_si256(X3_2, X3_3, 0 + (2 << 4))); + } + + _mm256_zeroupper(); +} + +#endif + +} + +static bool g_SSE2Enabled = false; +static bool g_SIMDInitialized = false; +#ifdef MY_CPU_AMD64 +static bool g_AVX2Enabled = false; +#endif + +static void InitSIMD() +{ + if (g_SIMDInitialized) + return; + g_SIMDInitialized = true; + +#ifdef MY_CPU_AMD64 + g_SSE2Enabled = true; + g_AVX2Enabled = CPU_IsSupported_AVX2() != 0; +#elif defined(MY_CPU_X86) + g_SSE2Enabled = CPU_IsSupported_SSE2() != 0; +#endif +} + +#endif + +#elif defined(MY_CPU_ARM_OR_ARM64) + +namespace { + +template +Z7_FORCE_INLINE uint32x4_t RotateLeft_NEON(const uint32x4_t val) +{ + return vorrq_u32(vshlq_n_u32(val, R), vshrq_n_u32(val, 32 - R)); +} + +template <> +Z7_FORCE_INLINE uint32x4_t RotateLeft_NEON<8>(const uint32x4_t val) +{ + static const uint8_t kMaskRot8[16] = {3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14}; + const uint8x16_t mask = vld1q_u8(kMaskRot8); + return vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(val), mask)); +} + +template <> +Z7_FORCE_INLINE uint32x4_t RotateLeft_NEON<16>(const uint32x4_t val) +{ + return vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(val))); +} + +Z7_FORCE_INLINE uint32x4_t Add64_NEON(const uint32x4_t a, const uint32x4_t b) +{ + return vreinterpretq_u32_u64(vaddq_u64(vreinterpretq_u64_u32(a), vreinterpretq_u64_u32(b))); +} + +template +Z7_FORCE_INLINE uint32x4_t Extract_NEON(const uint32x4_t val) +{ + return vextq_u32(val, val, S); +} + +#define NEON_QUARTERROUND(a, b, c, d) \ + a = vaddq_u32(a, b); \ + d = veorq_u32(d, a); \ + d = RotateLeft_NEON<16>(d); \ + c = vaddq_u32(c, d); \ + b = veorq_u32(b, c); \ + b = RotateLeft_NEON<12>(b); \ + a = vaddq_u32(a, b); \ + d = veorq_u32(d, a); \ + d = RotateLeft_NEON<8>(d); \ + c = vaddq_u32(c, d); \ + b = veorq_u32(b, c); \ + b = RotateLeft_NEON<7>(b); + +Z7_NO_INLINE void ChaCha20_OperateKeystream_NEON( + const UInt32 *state, + const Byte *input, + Byte *output) +{ + const uint32x4_t state0 = vld1q_u32(state + 0); + const uint32x4_t state1 = vld1q_u32(state + 4); + const uint32x4_t state2 = vld1q_u32(state + 8); + const uint32x4_t state3 = vld1q_u32(state + 12); + + const UInt32 CTR[12] = {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0}; + const uint32x4_t CTR1 = vld1q_u32(CTR + 0); + const uint32x4_t CTR2 = vld1q_u32(CTR + 4); + const uint32x4_t CTR3 = vld1q_u32(CTR + 8); + + uint32x4_t r0_0 = state0; + uint32x4_t r0_1 = state1; + uint32x4_t r0_2 = state2; + uint32x4_t r0_3 = state3; + + uint32x4_t r1_0 = state0; + uint32x4_t r1_1 = state1; + uint32x4_t r1_2 = state2; + uint32x4_t r1_3 = Add64_NEON(state3, CTR1); + + uint32x4_t r2_0 = state0; + uint32x4_t r2_1 = state1; + uint32x4_t r2_2 = state2; + uint32x4_t r2_3 = Add64_NEON(state3, CTR2); + + uint32x4_t r3_0 = state0; + uint32x4_t r3_1 = state1; + uint32x4_t r3_2 = state2; + uint32x4_t r3_3 = Add64_NEON(state3, CTR3); + + for (int i = 0; i < 10; i++) + { + NEON_QUARTERROUND(r0_0, r0_1, r0_2, r0_3); + NEON_QUARTERROUND(r1_0, r1_1, r1_2, r1_3); + NEON_QUARTERROUND(r2_0, r2_1, r2_2, r2_3); + NEON_QUARTERROUND(r3_0, r3_1, r3_2, r3_3); + + r0_1 = Extract_NEON<1>(r0_1); + r0_2 = Extract_NEON<2>(r0_2); + r0_3 = Extract_NEON<3>(r0_3); + + r1_1 = Extract_NEON<1>(r1_1); + r1_2 = Extract_NEON<2>(r1_2); + r1_3 = Extract_NEON<3>(r1_3); + + r2_1 = Extract_NEON<1>(r2_1); + r2_2 = Extract_NEON<2>(r2_2); + r2_3 = Extract_NEON<3>(r2_3); + + r3_1 = Extract_NEON<1>(r3_1); + r3_2 = Extract_NEON<2>(r3_2); + r3_3 = Extract_NEON<3>(r3_3); + + NEON_QUARTERROUND(r0_0, r0_1, r0_2, r0_3); + NEON_QUARTERROUND(r1_0, r1_1, r1_2, r1_3); + NEON_QUARTERROUND(r2_0, r2_1, r2_2, r2_3); + NEON_QUARTERROUND(r3_0, r3_1, r3_2, r3_3); + + r0_1 = Extract_NEON<3>(r0_1); + r0_2 = Extract_NEON<2>(r0_2); + r0_3 = Extract_NEON<1>(r0_3); + + r1_1 = Extract_NEON<3>(r1_1); + r1_2 = Extract_NEON<2>(r1_2); + r1_3 = Extract_NEON<1>(r1_3); + + r2_1 = Extract_NEON<3>(r2_1); + r2_2 = Extract_NEON<2>(r2_2); + r2_3 = Extract_NEON<1>(r2_3); + + r3_1 = Extract_NEON<3>(r3_1); + r3_2 = Extract_NEON<2>(r3_2); + r3_3 = Extract_NEON<1>(r3_3); + } + + r0_0 = vaddq_u32(r0_0, state0); + r0_1 = vaddq_u32(r0_1, state1); + r0_2 = vaddq_u32(r0_2, state2); + r0_3 = vaddq_u32(r0_3, state3); + + r1_0 = vaddq_u32(r1_0, state0); + r1_1 = vaddq_u32(r1_1, state1); + r1_2 = vaddq_u32(r1_2, state2); + r1_3 = vaddq_u32(r1_3, state3); + r1_3 = Add64_NEON(r1_3, CTR1); + + r2_0 = vaddq_u32(r2_0, state0); + r2_1 = vaddq_u32(r2_1, state1); + r2_2 = vaddq_u32(r2_2, state2); + r2_3 = vaddq_u32(r2_3, state3); + r2_3 = Add64_NEON(r2_3, CTR2); + + r3_0 = vaddq_u32(r3_0, state0); + r3_1 = vaddq_u32(r3_1, state1); + r3_2 = vaddq_u32(r3_2, state2); + r3_3 = vaddq_u32(r3_3, state3); + r3_3 = Add64_NEON(r3_3, CTR3); + + if (input) + { + r0_0 = veorq_u32(vld1q_u32((const UInt32 *)(input + 0*16)), r0_0); + r0_1 = veorq_u32(vld1q_u32((const UInt32 *)(input + 1*16)), r0_1); + r0_2 = veorq_u32(vld1q_u32((const UInt32 *)(input + 2*16)), r0_2); + r0_3 = veorq_u32(vld1q_u32((const UInt32 *)(input + 3*16)), r0_3); + } + + vst1q_u32((UInt32 *)(output + 0*16), r0_0); + vst1q_u32((UInt32 *)(output + 1*16), r0_1); + vst1q_u32((UInt32 *)(output + 2*16), r0_2); + vst1q_u32((UInt32 *)(output + 3*16), r0_3); + + if (input) + { + r1_0 = veorq_u32(vld1q_u32((const UInt32 *)(input + 4*16)), r1_0); + r1_1 = veorq_u32(vld1q_u32((const UInt32 *)(input + 5*16)), r1_1); + r1_2 = veorq_u32(vld1q_u32((const UInt32 *)(input + 6*16)), r1_2); + r1_3 = veorq_u32(vld1q_u32((const UInt32 *)(input + 7*16)), r1_3); + } + + vst1q_u32((UInt32 *)(output + 4*16), r1_0); + vst1q_u32((UInt32 *)(output + 5*16), r1_1); + vst1q_u32((UInt32 *)(output + 6*16), r1_2); + vst1q_u32((UInt32 *)(output + 7*16), r1_3); + + if (input) + { + r2_0 = veorq_u32(vld1q_u32((const UInt32 *)(input + 8*16)), r2_0); + r2_1 = veorq_u32(vld1q_u32((const UInt32 *)(input + 9*16)), r2_1); + r2_2 = veorq_u32(vld1q_u32((const UInt32 *)(input + 10*16)), r2_2); + r2_3 = veorq_u32(vld1q_u32((const UInt32 *)(input + 11*16)), r2_3); + } + + vst1q_u32((UInt32 *)(output + 8*16), r2_0); + vst1q_u32((UInt32 *)(output + 9*16), r2_1); + vst1q_u32((UInt32 *)(output + 10*16), r2_2); + vst1q_u32((UInt32 *)(output + 11*16), r2_3); + + if (input) + { + r3_0 = veorq_u32(vld1q_u32((const UInt32 *)(input + 12*16)), r3_0); + r3_1 = veorq_u32(vld1q_u32((const UInt32 *)(input + 13*16)), r3_1); + r3_2 = veorq_u32(vld1q_u32((const UInt32 *)(input + 14*16)), r3_2); + r3_3 = veorq_u32(vld1q_u32((const UInt32 *)(input + 15*16)), r3_3); + } + + vst1q_u32((UInt32 *)(output + 12*16), r3_0); + vst1q_u32((UInt32 *)(output + 13*16), r3_1); + vst1q_u32((UInt32 *)(output + 14*16), r3_2); + vst1q_u32((UInt32 *)(output + 15*16), r3_3); +} + +} + +static bool g_NEONEnabled = false; +static bool g_SIMDARMInitialized = false; + +static void InitSIMD() +{ + if (g_SIMDARMInitialized) + return; + g_SIMDARMInitialized = true; + g_NEONEnabled = CPU_IsSupported_NEON() != 0; +} + +#endif + +#endif \ No newline at end of file diff --git a/CPP/7zip/Crypto/HkdfBlake2sp.cpp b/CPP/7zip/Crypto/HkdfBlake2sp.cpp new file mode 100644 index 00000000..d8d96555 --- /dev/null +++ b/CPP/7zip/Crypto/HkdfBlake2sp.cpp @@ -0,0 +1,126 @@ +// HkdfBlake2sp.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include "HkdfBlake2sp.h" + +namespace NCrypto { +namespace NHkdfBlake2sp { + +#define BLAKE2SP_BLOCK_SIZE 64 + +#define Z7_HKDF_MAX_OUT_SIZE (255 * Z7_BLAKE2S_DIGEST_SIZE) + +static struct CBlake2sp_Prepare +{ + CBlake2sp_Prepare() { z7_Black2sp_Prepare(); } +} g_Blake2sp_Prepare; + +static void CloneBlake2spState(CBlake2sp *dest, const CBlake2sp *src) +{ + memcpy(dest, src, sizeof(CBlake2sp)); +} + +void Derive(const Byte *prk, unsigned prkSize, + const char *info, unsigned infoLen, + Byte *output, unsigned outSize) +{ + if (outSize > Z7_HKDF_MAX_OUT_SIZE) + return; + + Byte processedKey[Z7_BLAKE2S_DIGEST_SIZE]; + const Byte *effectiveKey; + unsigned effectiveKeySize; + + if (prkSize > BLAKE2SP_BLOCK_SIZE) + { + CAlignedBuffer1 bufHash(sizeof(CBlake2sp)); + CBlake2sp *blake2spHash = (CBlake2sp *)(void *)(Byte *)bufHash; + Blake2sp_Init(blake2spHash); + Blake2sp_SetFunction(blake2spHash, 0); + Blake2sp_Update(blake2spHash, prk, prkSize); + Blake2sp_Final(blake2spHash, processedKey); + + effectiveKey = processedKey; + effectiveKeySize = Z7_BLAKE2S_DIGEST_SIZE; + } + else + { + effectiveKey = prk; + effectiveKeySize = prkSize; + } + + Byte ipad[BLAKE2SP_BLOCK_SIZE]; + Byte opad[BLAKE2SP_BLOCK_SIZE]; + memset(ipad, 0x36, BLAKE2SP_BLOCK_SIZE); + memset(opad, 0x5c, BLAKE2SP_BLOCK_SIZE); + for (unsigned i = 0; i < effectiveKeySize; i++) + { + ipad[i] ^= effectiveKey[i]; + opad[i] ^= effectiveKey[i]; + } + + CAlignedBuffer1 bufInnerState(sizeof(CBlake2sp)); + CBlake2sp *innerState = (CBlake2sp *)(void *)(Byte *)bufInnerState; + Blake2sp_Init(innerState); + Blake2sp_SetFunction(innerState, 0); + Blake2sp_Update(innerState, ipad, BLAKE2SP_BLOCK_SIZE); + + CAlignedBuffer1 bufOuterState(sizeof(CBlake2sp)); + CBlake2sp *outerState = (CBlake2sp *)(void *)(Byte *)bufOuterState; + Blake2sp_Init(outerState); + Blake2sp_SetFunction(outerState, 0); + Blake2sp_Update(outerState, opad, BLAKE2SP_BLOCK_SIZE); + + const unsigned n = (outSize + Z7_BLAKE2S_DIGEST_SIZE - 1) / Z7_BLAKE2S_DIGEST_SIZE; + + Byte prevT[Z7_BLAKE2S_DIGEST_SIZE]; + unsigned prevTSize = 0; + + Byte *outPtr = output; + unsigned remaining = outSize; + + CAlignedBuffer1 bufInnerTmp(sizeof(CBlake2sp)); + CAlignedBuffer1 bufOuterTmp(sizeof(CBlake2sp)); + CBlake2sp *innerTmp = (CBlake2sp *)(void *)(Byte *)bufInnerTmp; + CBlake2sp *outerTmp = (CBlake2sp *)(void *)(Byte *)bufOuterTmp; + + for (unsigned i = 1; i <= n; i++) + { + CloneBlake2spState(innerTmp, innerState); + if (prevTSize > 0) + Blake2sp_Update(innerTmp, prevT, prevTSize); + if (infoLen > 0) + Blake2sp_Update(innerTmp, (const Byte *)info, infoLen); + const Byte counter = (Byte)i; + Blake2sp_Update(innerTmp, &counter, 1); + + Byte innerHash[Z7_BLAKE2S_DIGEST_SIZE]; + Blake2sp_Final(innerTmp, innerHash); + CloneBlake2spState(outerTmp, outerState); + Blake2sp_Update(outerTmp, innerHash, Z7_BLAKE2S_DIGEST_SIZE); + + Byte ti[Z7_BLAKE2S_DIGEST_SIZE]; + Blake2sp_Final(outerTmp, ti); + + const unsigned copySize = remaining < Z7_BLAKE2S_DIGEST_SIZE ? remaining : Z7_BLAKE2S_DIGEST_SIZE; + memcpy(outPtr, ti, copySize); + outPtr += copySize; + remaining -= copySize; + + memcpy(prevT, ti, Z7_BLAKE2S_DIGEST_SIZE); + prevTSize = Z7_BLAKE2S_DIGEST_SIZE; + + Z7_memset_0_ARRAY(ti); + Z7_memset_0_ARRAY(innerHash); + } + + Z7_memset_0_ARRAY(prevT); + Z7_memset_0_ARRAY(ipad); + Z7_memset_0_ARRAY(opad); + Z7_memset_0_ARRAY(processedKey); +} + +}} \ No newline at end of file diff --git a/CPP/7zip/Crypto/HkdfBlake2sp.h b/CPP/7zip/Crypto/HkdfBlake2sp.h new file mode 100644 index 00000000..2454acce --- /dev/null +++ b/CPP/7zip/Crypto/HkdfBlake2sp.h @@ -0,0 +1,20 @@ +// HkdfBlake2sp.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_INC_CRYPTO_HKDF_BLAKE2SP_H +#define ZIP7_INC_CRYPTO_HKDF_BLAKE2SP_H + +#include "../../../C/Blake2.h" +#include "../../Common/MyBuffer2.h" + +namespace NCrypto { +namespace NHkdfBlake2sp { + +void Derive(const Byte *prk, unsigned prkSize, + const char *info, unsigned infoLen, + Byte *output, unsigned outSize); + +}} + +#endif diff --git a/CPP/7zip/Crypto/HmacSha512.cpp b/CPP/7zip/Crypto/HmacSha512.cpp new file mode 100644 index 00000000..ef477bd9 --- /dev/null +++ b/CPP/7zip/Crypto/HmacSha512.cpp @@ -0,0 +1,55 @@ +// HmacSha512.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include + +#include "../../../C/CpuArch.h" + +#include "HmacSha512.h" + +namespace NCrypto { +namespace NSha512 { + +void CHmac::SetKey(const Byte *key, size_t keySize) +{ + MY_ALIGN (16) + UInt64 temp[SHA512_NUM_BLOCK_WORDS]; + size_t i; + + for (i = 0; i < SHA512_NUM_BLOCK_WORDS; i++) + temp[i] = 0; + + if (keySize > kBlockSize) + { + Sha512_Init(&_sha, SHA512_DIGEST_SIZE); + Sha512_Update(&_sha, key, keySize); + Sha512_Final(&_sha, (Byte *)temp, SHA512_DIGEST_SIZE); + } + else + memcpy(temp, key, keySize); + + for (i = 0; i < SHA512_NUM_BLOCK_WORDS; i++) + temp[i] ^= UINT64_CONST(0x3636363636363636); + + Sha512_Init(&_sha, SHA512_DIGEST_SIZE); + Sha512_Update(&_sha, (const Byte *)temp, kBlockSize); + + for (i = 0; i < SHA512_NUM_BLOCK_WORDS; i++) + temp[i] ^= UINT64_CONST(0x3636363636363636) ^ UINT64_CONST(0x5C5C5C5C5C5C5C5C); + + Sha512_Init(&_sha2, SHA512_DIGEST_SIZE); + Sha512_Update(&_sha2, (const Byte *)temp, kBlockSize); +} + + +void CHmac::Final(Byte *mac) +{ + Sha512_Final(&_sha, mac, SHA512_DIGEST_SIZE); + Sha512_Update(&_sha2, mac, SHA512_DIGEST_SIZE); + Sha512_Final(&_sha2, mac, SHA512_DIGEST_SIZE); +} + +}} diff --git a/CPP/7zip/Crypto/HmacSha512.h b/CPP/7zip/Crypto/HmacSha512.h new file mode 100644 index 00000000..ce337d91 --- /dev/null +++ b/CPP/7zip/Crypto/HmacSha512.h @@ -0,0 +1,29 @@ +// HmacSha512.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_INC_CRYPTO_HMAC_SHA512_H +#define ZIP7_INC_CRYPTO_HMAC_SHA512_H + +#include "../../../C/Sha512.h" + +namespace NCrypto { +namespace NSha512 { + +const unsigned kBlockSize = SHA512_BLOCK_SIZE; +const unsigned kDigestSize = SHA512_DIGEST_SIZE; +const unsigned kNumDigestWords = SHA512_NUM_DIGEST_WORDS; + +class CHmac +{ + CSha512 _sha; + CSha512 _sha2; +public: + void SetKey(const Byte *key, size_t keySize); + void Update(const Byte *data, size_t dataSize) { Sha512_Update(&_sha, data, dataSize); } + void Final(Byte *mac); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha512.cpp b/CPP/7zip/Crypto/Pbkdf2HmacSha512.cpp new file mode 100644 index 00000000..55f97285 --- /dev/null +++ b/CPP/7zip/Crypto/Pbkdf2HmacSha512.cpp @@ -0,0 +1,63 @@ +// Pbkdf2HmacSha512.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include + +#include "../../../C/CpuArch.h" + +#include "HmacSha512.h" +#include "Pbkdf2HmacSha512.h" + +namespace NCrypto { +namespace NSha512 { + +void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, + const Byte *salt, size_t saltSize, + UInt32 numIterations, + Byte *key, size_t keySize) +{ + MY_ALIGN (16) + CHmac baseCtx; + baseCtx.SetKey(pwd, pwdSize); + + for (UInt32 i = 1; keySize != 0; i++) + { + MY_ALIGN (16) + CHmac ctx; + ctx = baseCtx; + ctx.Update(salt, saltSize); + + MY_ALIGN (16) + UInt32 be_i[1]; + SetBe32(be_i, i) + + ctx.Update((const Byte *)be_i, 4); + + MY_ALIGN (16) + Byte u[kDigestSize]; + ctx.Final(u); + + MY_ALIGN (16) + Byte t[kDigestSize]; + memcpy(t, u, kDigestSize); + + for (UInt32 j = 1; j < numIterations; j++) + { + ctx = baseCtx; + ctx.Update(u, kDigestSize); + ctx.Final(u); + for (unsigned k = 0; k < kDigestSize; k++) + t[k] ^= u[k]; + } + + const unsigned curSize = (keySize < kDigestSize) ? (unsigned)keySize : kDigestSize; + memcpy(key, t, curSize); + key += curSize; + keySize -= curSize; + } +} + +}} diff --git a/CPP/7zip/Crypto/Pbkdf2HmacSha512.h b/CPP/7zip/Crypto/Pbkdf2HmacSha512.h new file mode 100644 index 00000000..78236bd1 --- /dev/null +++ b/CPP/7zip/Crypto/Pbkdf2HmacSha512.h @@ -0,0 +1,20 @@ +// Pbkdf2HmacSha512.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_INC_CRYPTO_PBKDF2_HMAC_SHA512_H +#define ZIP7_INC_CRYPTO_PBKDF2_HMAC_SHA512_H + +#include + +#include "../../Common/MyTypes.h" + +namespace NCrypto { +namespace NSha512 { + +void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize, + UInt32 numIterations, Byte *key, size_t keySize); + +}} + +#endif diff --git a/CPP/7zip/Crypto/Rar5Aes.h b/CPP/7zip/Crypto/Rar5Aes.h index c6059aa2..81e42e43 100644 --- a/CPP/7zip/Crypto/Rar5Aes.h +++ b/CPP/7zip/Crypto/Rar5Aes.h @@ -22,6 +22,14 @@ namespace NCryptoFlags const unsigned kUseMAC = 1 << 1; } +inline bool ConstantTimeCompare(const Byte *a, const Byte *b, size_t size) +{ + volatile Byte result = 0; + for (size_t i = 0; i < size; i++) + result |= a[i] ^ b[i]; + return result == 0; +} + struct CKeyBase { protected: @@ -49,9 +57,13 @@ struct CKey: public CKeyBase bool IsKeyEqualTo(const CKey &key) { - return _numIterationsLog == key._numIterationsLog - && memcmp(_salt, key._salt, sizeof(_salt)) == 0 - && _password == key._password; + if (_numIterationsLog != key._numIterationsLog) + return false; + if (!ConstantTimeCompare(_salt, key._salt, sizeof(_salt))) + return false; + if (_password.Size() != key._password.Size()) + return false; + return ConstantTimeCompare(_password, key._password, _password.Size()); } CKey(); @@ -79,6 +91,7 @@ class CDecoder Z7_final: Byte _iv[AES_BLOCK_SIZE]; CDecoder(); + ~CDecoder() { Z7_memset_0_ARRAY(_iv); } Z7_COM7F_IMP(Init()) diff --git a/CPP/7zip/Crypto/XChaCha20.cpp b/CPP/7zip/Crypto/XChaCha20.cpp new file mode 100644 index 00000000..f4bec76b --- /dev/null +++ b/CPP/7zip/Crypto/XChaCha20.cpp @@ -0,0 +1,510 @@ +// XChaCha20.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../../Common/ComTry.h" + +#ifndef Z7_ST +#include "../../Windows/Synchronization.h" +#endif + +#include "../Common/StreamUtils.h" + +#include "XChaCha20.h" + +#ifndef Z7_EXTRACT_ONLY +#include "RandGen.h" +#endif + +#include "ChaCha20Simd.h" + +namespace NCrypto { +namespace NXChaCha20 { + +#define ROTL32(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) + +#define QUARTERROUND(a, b, c, d) \ + a += b; d ^= a; d = ROTL32(d, 16); \ + c += d; b ^= c; b = ROTL32(b, 12); \ + a += b; d ^= a; d = ROTL32(d, 8); \ + c += d; b ^= c; b = ROTL32(b, 7); + +#define CHACHA20_10_DOUBLE_ROUNDS \ + DOUBLE_ROUND; DOUBLE_ROUND; \ + DOUBLE_ROUND; DOUBLE_ROUND; \ + DOUBLE_ROUND; DOUBLE_ROUND; \ + DOUBLE_ROUND; DOUBLE_ROUND; \ + DOUBLE_ROUND; DOUBLE_ROUND; + +static CKeyInfoCache g_GlobalKeyCache(32); + +#ifndef Z7_ST + static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection; + #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection); +#else + #define MT_LOCK +#endif + +CBase::CBase(): + _cachedKeys(16), + _counter(0) +{ + for (unsigned i = 0; i < sizeof(_nonce); i++) + _nonce[i] = 0; +} + +void CBaseCoder::DeriveKey() +{ + XHChaCha20Block_Core(_derivedKey, _key.Key, _nonce); + _derivedKeyValid = true; +} + +void CBase::PrepareKey() +{ + MT_LOCK + + bool finded = false; + if (!_cachedKeys.GetKey(_key)) + { + finded = g_GlobalKeyCache.GetKey(_key); + if (!finded) + _key.CalcKey(); + _cachedKeys.Add(_key); + } + if (!finded) + g_GlobalKeyCache.FindAndAdd(_key); +} + +#define DOUBLE_ROUND \ + QUARTERROUND(x0, x4, x8, x12) \ + QUARTERROUND(x1, x5, x9, x13) \ + QUARTERROUND(x2, x6, x10, x14) \ + QUARTERROUND(x3, x7, x11, x15) \ + QUARTERROUND(x0, x5, x10, x15) \ + QUARTERROUND(x1, x6, x11, x12) \ + QUARTERROUND(x2, x7, x8, x13) \ + QUARTERROUND(x3, x4, x9, x14) + +void XHChaCha20Block_Core(Byte *output, const Byte *key, const Byte *nonce) +{ + UInt32 x0, x1, x2, x3, x4, x5, x6, x7; + UInt32 x8, x9, x10, x11, x12, x13, x14, x15; + + x0 = GetUi32(kSigma); + x1 = GetUi32(kSigma + 4); + x2 = GetUi32(kSigma + 8); + x3 = GetUi32(kSigma + 12); + + x4 = GetUi32(key); + x5 = GetUi32(key + 4); + x6 = GetUi32(key + 8); + x7 = GetUi32(key + 12); + x8 = GetUi32(key + 16); + x9 = GetUi32(key + 20); + x10 = GetUi32(key + 24); + x11 = GetUi32(key + 28); + + x12 = GetUi32(nonce); + x13 = GetUi32(nonce + 4); + x14 = GetUi32(nonce + 8); + x15 = GetUi32(nonce + 12); + + CHACHA20_10_DOUBLE_ROUNDS + + SetUi32(output, x0); + SetUi32(output + 4, x1); + SetUi32(output + 8, x2); + SetUi32(output + 12, x3); + SetUi32(output + 16, x12); + SetUi32(output + 20, x13); + SetUi32(output + 24, x14); + SetUi32(output + 28, x15); +} + +void XChaCha20Block_Core(Byte *output, const Byte *key, const Byte *nonce, UInt64 counter) +{ + UInt32 x0, x1, x2, x3, x4, x5, x6, x7; + UInt32 x8, x9, x10, x11, x12, x13, x14, x15; + + x0 = GetUi32(kSigma); + x1 = GetUi32(kSigma + 4); + x2 = GetUi32(kSigma + 8); + x3 = GetUi32(kSigma + 12); + + x4 = GetUi32(key); + x5 = GetUi32(key + 4); + x6 = GetUi32(key + 8); + x7 = GetUi32(key + 12); + x8 = GetUi32(key + 16); + x9 = GetUi32(key + 20); + x10 = GetUi32(key + 24); + x11 = GetUi32(key + 28); + + x12 = (UInt32)(counter & 0xFFFFFFFF); + x13 = (UInt32)(counter >> 32); + x14 = GetUi32(nonce); + x15 = GetUi32(nonce + 4); + + CHACHA20_10_DOUBLE_ROUNDS + + x0 += GetUi32(kSigma); + x1 += GetUi32(kSigma + 4); + x2 += GetUi32(kSigma + 8); + x3 += GetUi32(kSigma + 12); + x4 += GetUi32(key); + x5 += GetUi32(key + 4); + x6 += GetUi32(key + 8); + x7 += GetUi32(key + 12); + x8 += GetUi32(key + 16); + x9 += GetUi32(key + 20); + x10 += GetUi32(key + 24); + x11 += GetUi32(key + 28); + x12 += (UInt32)(counter & 0xFFFFFFFF); + x13 += (UInt32)(counter >> 32); + x14 += GetUi32(nonce); + x15 += GetUi32(nonce + 4); + + SetUi32(output, x0); + SetUi32(output + 4, x1); + SetUi32(output + 8, x2); + SetUi32(output + 12, x3); + SetUi32(output + 16, x4); + SetUi32(output + 20, x5); + SetUi32(output + 24, x6); + SetUi32(output + 28, x7); + SetUi32(output + 32, x8); + SetUi32(output + 36, x9); + SetUi32(output + 40, x10); + SetUi32(output + 44, x11); + SetUi32(output + 48, x12); + SetUi32(output + 52, x13); + SetUi32(output + 56, x14); + SetUi32(output + 60, x15); +} + +#undef DOUBLE_ROUND + +void XChaCha20ProcessData(Byte *data, UInt32 size, const Byte *derivedKey, const Byte *nonce, UInt64 &counter, Byte *block, unsigned &blockPos) +{ + if (blockPos > 0 && blockPos < kBlockBytes) + { + UInt32 remaining = kBlockBytes - blockPos; + UInt32 toProcess = (size < remaining) ? size : remaining; + Byte *dataPtr = data; + const Byte *blockPtr = block + blockPos; + UInt32 count = toProcess; +#ifdef MY_CPU_LE_UNALIGN_64 + while (count >= 8) + { + *(UInt64 *)dataPtr ^= *(const UInt64 *)blockPtr; + dataPtr += 8; + blockPtr += 8; + count -= 8; + } +#endif +#ifdef MY_CPU_LE_UNALIGN + while (count >= 4) + { + *(UInt32 *)dataPtr ^= *(const UInt32 *)blockPtr; + dataPtr += 4; + blockPtr += 4; + count -= 4; + } +#endif + while (count--) + *dataPtr++ ^= *blockPtr++; + data += toProcess; + size -= toProcess; + blockPos += toProcess; + } + +#ifdef MY_CPU_X86_OR_AMD64 +#ifdef MY_CPU_SSE2 + InitSIMD(); + + if (size >= kBlockBytes * 4) + { + UInt32 state[16]; + state[0] = GetUi32(kSigma); + state[1] = GetUi32(kSigma + 4); + state[2] = GetUi32(kSigma + 8); + state[3] = GetUi32(kSigma + 12); + state[4] = GetUi32(derivedKey); + state[5] = GetUi32(derivedKey + 4); + state[6] = GetUi32(derivedKey + 8); + state[7] = GetUi32(derivedKey + 12); + state[8] = GetUi32(derivedKey + 16); + state[9] = GetUi32(derivedKey + 20); + state[10] = GetUi32(derivedKey + 24); + state[11] = GetUi32(derivedKey + 28); + state[12] = (UInt32)(counter & 0xFFFFFFFF); + state[13] = (UInt32)(counter >> 32); + state[14] = GetUi32(nonce + 16); + state[15] = GetUi32(nonce + 20); + +#ifdef MY_CPU_AMD64 + if (g_AVX2Enabled && size >= kBlockBytes * 8) + { + while (size >= kBlockBytes * 8) + { + ChaCha20_OperateKeystream_AVX2(state, data, data); + state[12] += 8; + if (state[12] < 8) + state[13]++; + data += kBlockBytes * 8; + size -= kBlockBytes * 8; + } + } +#endif + + if (g_SSE2Enabled && size >= kBlockBytes * 4) + { + while (size >= kBlockBytes * 4) + { + ChaCha20_OperateKeystream_SSE2(state, data, data); + state[12] += 4; + if (state[12] < 4) + state[13]++; + data += kBlockBytes * 4; + size -= kBlockBytes * 4; + } + } + + counter = (UInt64)state[13] << 32 | state[12]; + blockPos = kBlockBytes; + } +#endif +#endif + +#ifdef MY_CPU_ARM_OR_ARM64 + InitSIMD(); + + if (g_NEONEnabled && size >= kBlockBytes * 4) + { + UInt32 state[16]; + state[0] = GetUi32(kSigma); + state[1] = GetUi32(kSigma + 4); + state[2] = GetUi32(kSigma + 8); + state[3] = GetUi32(kSigma + 12); + state[4] = GetUi32(derivedKey); + state[5] = GetUi32(derivedKey + 4); + state[6] = GetUi32(derivedKey + 8); + state[7] = GetUi32(derivedKey + 12); + state[8] = GetUi32(derivedKey + 16); + state[9] = GetUi32(derivedKey + 20); + state[10] = GetUi32(derivedKey + 24); + state[11] = GetUi32(derivedKey + 28); + state[12] = (UInt32)(counter & 0xFFFFFFFF); + state[13] = (UInt32)(counter >> 32); + state[14] = GetUi32(nonce + 16); + state[15] = GetUi32(nonce + 20); + + while (size >= kBlockBytes * 4) + { + ChaCha20_OperateKeystream_NEON(state, data, data); + state[12] += 4; + if (state[12] < 4) + state[13]++; + data += kBlockBytes * 4; + size -= kBlockBytes * 4; + } + + counter = (UInt64)state[13] << 32 | state[12]; + blockPos = kBlockBytes; + } +#endif + + while (size > 0) + { + if (blockPos == 0 || blockPos >= kBlockBytes) + { + XChaCha20Block_Core(block, derivedKey, nonce + 16, counter); + blockPos = 0; + counter++; + } + + UInt32 remaining = kBlockBytes - blockPos; + UInt32 toProcess = (size < remaining) ? size : remaining; + + Byte *dataPtr = data; + const Byte *blockPtr = block + blockPos; + UInt32 count = toProcess; + +#ifdef MY_CPU_LE_UNALIGN_64 + while (count >= 8) + { + *(UInt64 *)dataPtr ^= *(const UInt64 *)blockPtr; + dataPtr += 8; + blockPtr += 8; + count -= 8; + } +#endif + +#ifdef MY_CPU_LE_UNALIGN + while (count >= 4) + { + *(UInt32 *)dataPtr ^= *(const UInt32 *)blockPtr; + dataPtr += 4; + blockPtr += 4; + count -= 4; + } +#endif + + while (count--) + *dataPtr++ ^= *blockPtr++; + + data += toProcess; + size -= toProcess; + blockPos += toProcess; + } +} + +void CBaseCoder::ProcessData(Byte *data, UInt32 size) +{ + if (!_derivedKeyValid) + { + DeriveKey(); + } + XChaCha20ProcessData(data, size, _derivedKey, _nonce, _counter, _block, _blockPos); +} + +#ifndef Z7_EXTRACT_ONLY + +Z7_COM7F_IMF(CEncoder::ResetInitVector()) +{ + for (unsigned i = 0; i < sizeof(_nonce); i++) + _nonce[i] = 0; + MY_RAND_GEN(_nonce, kNonceSize); + _counter = 0; + _blockPos = kBlockSize; + _derivedKeyValid = false; + return S_OK; +} + +Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) +{ + Byte props[2 + sizeof(_key.Salt) + kNonceSize]; + unsigned propsSize = 1; + + const unsigned nonceSizeMinus1 = kNonceSize - 1; + const unsigned nonceHigh = (nonceSizeMinus1 >= 16) ? (1 << 6) : 0; + const unsigned nonceLow = nonceSizeMinus1 & 0x0F; + + props[0] = (Byte)(_key.NumCyclesPower + | (_key.SaltSize == 0 ? 0 : (1 << 7)) + | nonceHigh); + + if (_key.SaltSize != 0) + { + props[1] = (Byte)( + ((_key.SaltSize - 1) << 4) + | nonceLow); + memcpy(props + 2, _key.Salt, _key.SaltSize); + propsSize = 2 + _key.SaltSize; + memcpy(props + propsSize, _nonce, kNonceSize); + propsSize += kNonceSize; + } + else + { + props[1] = (Byte)(nonceLow); + propsSize = 2; + memcpy(props + propsSize, _nonce, kNonceSize); + propsSize += kNonceSize; + } + + return WriteStream(outStream, props, propsSize); +} + +CEncoder::CEncoder() +{ + _key.NumCyclesPower = 19; + _counter = 0; + _blockPos = kBlockSize; + _derivedKeyValid = false; +} + +#endif + +CDecoder::CDecoder() +{ + _counter = 0; + _blockPos = kBlockSize; + _derivedKeyValid = false; +} + +Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)) +{ + _key.ClearProps(); + + _counter = 0; + _blockPos = kBlockSize; + _derivedKeyValid = false; + unsigned i; + for (i = 0; i < sizeof(_nonce); i++) + _nonce[i] = 0; + + if (size == 0) + return S_OK; + + const unsigned b0 = data[0]; + _key.NumCyclesPower = b0 & 0x3F; + if ((b0 & 0xC0) == 0) + return size == 1 ? S_OK : E_INVALIDARG; + if (size <= 1) + return E_INVALIDARG; + + const unsigned b1 = data[1]; + const unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4); + const unsigned nonceSizeMinus1 = ((b0 >> 6) & 1) * 16 + (b1 & 0x0F); + const unsigned nonceSize = nonceSizeMinus1 + 1; + + if (size != 2 + saltSize + nonceSize) + return E_INVALIDARG; + _key.SaltSize = saltSize; + data += 2; + for (i = 0; i < saltSize; i++) + _key.Salt[i] = *data++; + for (i = 0; i < nonceSize && i < kNonceSize; i++) + _nonce[i] = *data++; + + return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX + || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL; +} + + +Z7_COM7F_IMF(CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)) +{ + COM_TRY_BEGIN + + _key.Password.Wipe(); + _key.Password.CopyFrom(data, (size_t)size); + _derivedKeyValid = false; + return S_OK; + + COM_TRY_END +} + +Z7_COM7F_IMF(CBaseCoder::Init()) +{ + COM_TRY_BEGIN + + PrepareKey(); + _counter = 0; + _blockPos = kBlockSize; + _derivedKeyValid = false; + return S_OK; + + COM_TRY_END +} + +Z7_COM7F_IMF2(UInt32, CBaseCoder::Filter(Byte *data, UInt32 size)) +{ + ProcessData(data, size); + return size; +} + +}} diff --git a/CPP/7zip/Crypto/XChaCha20.h b/CPP/7zip/Crypto/XChaCha20.h new file mode 100644 index 00000000..cc8745d7 --- /dev/null +++ b/CPP/7zip/Crypto/XChaCha20.h @@ -0,0 +1,107 @@ +// XChaCha20.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_INC_CRYPTO_XCHACHA20_H +#define ZIP7_INC_CRYPTO_XCHACHA20_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +#include "7zKeyDerivation.h" + +namespace NCrypto { +namespace NXChaCha20 { + +using CKeyInfo = N7zKeyDerivation::CKeyInfo; +using CKeyInfoCache = N7zKeyDerivation::CKeyInfoCache; + +using N7zKeyDerivation::kKeySize; + +const unsigned kNonceSize = 24; +const unsigned k_NumCyclesPower_Supported_MAX = 24; +const unsigned kBlockBytes = 64; + +void XChaCha20Block_Core(Byte *output, const Byte *key, const Byte *nonce, UInt64 counter); +void XHChaCha20Block_Core(Byte *output, const Byte *key, const Byte *nonce); +void XChaCha20ProcessData(Byte *data, UInt32 size, const Byte *derivedKey, const Byte *nonce, UInt64 &counter, Byte *block, unsigned &blockPos); + +class CBase +{ + CKeyInfoCache _cachedKeys; +protected: + CKeyInfo _key; + Byte _nonce[kNonceSize]; + UInt64 _counter; + + void PrepareKey(); + CBase(); + ~CBase() + { + Z7_memset_0_ARRAY(_nonce); + } +}; + +class CBaseCoder: + public ICompressFilter, + public ICryptoSetPassword, + public CMyUnknownImp, + public CBase +{ + Z7_IFACE_COM7_IMP_NONFINAL(ICompressFilter) + Z7_IFACE_COM7_IMP_NONFINAL(ICryptoSetPassword) +protected: + virtual ~CBaseCoder() + { + Z7_memset_0_ARRAY(_block); + Z7_memset_0_ARRAY(_derivedKey); + } + + static const unsigned kBlockSize = 64; + Byte _block[kBlockSize]; + unsigned _blockPos; + Byte _derivedKey[kKeySize]; + bool _derivedKeyValid; + + void ProcessData(Byte *data, UInt32 size); + virtual void DeriveKey(); +}; + +#ifndef Z7_EXTRACT_ONLY + +class CEncoder Z7_final: + public CBaseCoder, + public ICompressWriteCoderProperties, + public ICryptoResetInitVector +{ + Z7_COM_UNKNOWN_IMP_4( + ICompressFilter, + ICryptoSetPassword, + ICompressWriteCoderProperties, + ICryptoResetInitVector) + Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties) + Z7_IFACE_COM7_IMP(ICryptoResetInitVector) +public: + CEncoder(); +}; + +#endif + +class CDecoder Z7_final: + public CBaseCoder, + public ICompressSetDecoderProperties2 +{ + Z7_COM_UNKNOWN_IMP_3( + ICompressFilter, + ICryptoSetPassword, + ICompressSetDecoderProperties2) + Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) +public: + CDecoder(); +}; + +}} + +#endif diff --git a/CPP/7zip/Crypto/XChaCha20Poly1305.cpp b/CPP/7zip/Crypto/XChaCha20Poly1305.cpp new file mode 100644 index 00000000..591d71d1 --- /dev/null +++ b/CPP/7zip/Crypto/XChaCha20Poly1305.cpp @@ -0,0 +1,485 @@ +// XChaCha20Poly1305.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include "../../../C/CpuArch.h" + +#include "../../Common/ComTry.h" + +#ifndef Z7_ST +#include "../../Windows/Synchronization.h" +#endif + +#include "../Common/StreamUtils.h" + +#include "XChaCha20Poly1305.h" + +#ifndef Z7_EXTRACT_ONLY +#include "RandGen.h" +#endif + +#if defined(MY_CPU_AMD64) + #ifdef _MSC_VER + #include + #else + #include + #endif + #define Z7_POLY1305_128BIT +#endif + +namespace NCrypto { +namespace NXChaCha20Poly1305 { + +void CBaseCoder::ComputePolyKey() +{ + Byte polyBlock[64]; + NXChaCha20::XChaCha20Block_Core(polyBlock, _derivedKey, _nonce + 16, 0); + memcpy(_polyKey, polyBlock, kPolyKeySize); + Z7_memset_0_ARRAY(polyBlock); +} + +CPoly1305::CPoly1305() +{ + Reset(); +} + +void CPoly1305::Reset() +{ + memset(_r, 0, sizeof(_r)); + memset(_s, 0, sizeof(_s)); + memset(_h, 0, sizeof(_h)); + memset(_n, 0, sizeof(_n)); + memset(_block, 0, sizeof(_block)); + _blockPos = 0; + _totalLen = 0; + memset(_aadBlock, 0, sizeof(_aadBlock)); + _aadBlockPos = 0; + _aadLen = 0; + _finalized = false; +} + +void CPoly1305::SetKey(const Byte *key) +{ + Reset(); + + _r[0] = GetUi32(key) & 0x0fffffff; + _r[1] = GetUi32(key + 4) & 0x0ffffffc; + _r[2] = GetUi32(key + 8) & 0x0ffffffc; + _r[3] = GetUi32(key + 12) & 0x0ffffffc; + + _s[1] = _r[1] + (_r[1] >> 2); + _s[2] = _r[2] + (_r[2] >> 2); + _s[3] = _r[3] + (_r[3] >> 2); + + _n[0] = GetUi32(key + 16); + _n[1] = GetUi32(key + 20); + _n[2] = GetUi32(key + 24); + _n[3] = GetUi32(key + 28); +} + +static inline UInt32 CONSTANT_TIME_CARRY(UInt32 a, UInt32 b) +{ + return ((a ^ ((a ^ b) | ((a - b) ^ b))) >> 31); +} + +static void Poly1305_ProcessBlock(UInt32 h[5], const UInt32 r[4], const UInt32 s[4], const Byte block[16], bool hasHighBit) +{ + UInt32 r0 = r[0], r1 = r[1], r2 = r[2], r3 = r[3]; + UInt32 s1 = s[1], s2 = s[2], s3 = s[3]; + UInt32 h0 = h[0], h1 = h[1], h2 = h[2], h3 = h[3], h4 = h[4]; + UInt64 d0, d1, d2, d3; + UInt32 c; + + h0 = (UInt32)(d0 = (UInt64)h0 + GetUi32(block)); + h1 = (UInt32)(d1 = (UInt64)h1 + (d0 >> 32) + GetUi32(block + 4)); + h2 = (UInt32)(d2 = (UInt64)h2 + (d1 >> 32) + GetUi32(block + 8)); + h3 = (UInt32)(d3 = (UInt64)h3 + (d2 >> 32) + GetUi32(block + 12)); + h4 += (UInt32)(d3 >> 32) + (hasHighBit ? 1 : 0); + + d0 = ((UInt64)h0 * r0) + + ((UInt64)h1 * s3) + + ((UInt64)h2 * s2) + + ((UInt64)h3 * s1); + d1 = ((UInt64)h0 * r1) + + ((UInt64)h1 * r0) + + ((UInt64)h2 * s3) + + ((UInt64)h3 * s2) + + ((UInt64)h4 * s1); + d2 = ((UInt64)h0 * r2) + + ((UInt64)h1 * r1) + + ((UInt64)h2 * r0) + + ((UInt64)h3 * s3) + + ((UInt64)h4 * s2); + d3 = ((UInt64)h0 * r3) + + ((UInt64)h1 * r2) + + ((UInt64)h2 * r1) + + ((UInt64)h3 * r0) + + ((UInt64)h4 * s3); + h4 = (UInt32)(h4 * r0); + + h0 = (UInt32)d0; + h1 = (UInt32)(d1 += d0 >> 32); + h2 = (UInt32)(d2 += d1 >> 32); + h3 = (UInt32)(d3 += d2 >> 32); + h4 += (UInt32)(d3 >> 32); + + c = (h4 >> 2) + (h4 & ~3U); + h4 &= 3; + h0 += c; + h1 += (c = CONSTANT_TIME_CARRY(h0, c)); + h2 += (c = CONSTANT_TIME_CARRY(h1, c)); + h3 += (c = CONSTANT_TIME_CARRY(h2, c)); + h4 += CONSTANT_TIME_CARRY(h3, c); + + h[0] = h0; h[1] = h1; h[2] = h2; + h[3] = h3; h[4] = h4; +} + +void CPoly1305::ProcessBlocks(Byte *buf, unsigned &bufPos, UInt64 &len, const Byte *data, UInt32 size) +{ + len += size; + + if (bufPos > 0) + { + unsigned n = 16 - bufPos; + if (n > size) n = size; + memcpy(buf + bufPos, data, n); + bufPos += n; + data += n; + size -= n; + if (bufPos == 16) + { + Poly1305_ProcessBlock(_h, _r, _s, buf, true); + bufPos = 0; + } + } + + while (size >= 16) + { + Poly1305_ProcessBlock(_h, _r, _s, data, true); + data += 16; + size -= 16; + } + + if (size > 0) + { + memcpy(buf, data, size); + bufPos = size; + } +} + +void CPoly1305::Update(const Byte *data, UInt32 size) +{ + if (_finalized) return; + ProcessBlocks(_block, _blockPos, _totalLen, data, size); +} + +void CPoly1305::UpdateAad(const Byte *data, UInt32 size) +{ + if (_finalized) return; + ProcessBlocks(_aadBlock, _aadBlockPos, _aadLen, data, size); +} + +void CPoly1305::PadAndProcessBlock(Byte *buf, unsigned bufPos) +{ + if (bufPos != 0) + { + memset(buf + bufPos, 0, 16 - bufPos); + buf[bufPos] = 1; + Poly1305_ProcessBlock(_h, _r, _s, buf, false); + } +} + +void CPoly1305::Final(Byte *tag) +{ + if (_finalized) + return; + _finalized = true; + + PadAndProcessBlock(_aadBlock, _aadBlockPos); + PadAndProcessBlock(_block, _blockPos); + + { + Byte lenBlock[16]; + for (unsigned i = 0; i < 8; i++) + lenBlock[i] = (Byte)(_aadLen >> (i * 8)); + for (unsigned i = 0; i < 8; i++) + lenBlock[8 + i] = (Byte)(_totalLen >> (i * 8)); + Poly1305_ProcessBlock(_h, _r, _s, lenBlock, true); + } + + UInt32 h0 = _h[0], h1 = _h[1], h2 = _h[2], h3 = _h[3], h4 = _h[4]; + UInt32 g0, g1, g2, g3, g4; + UInt32 mask; + UInt64 t; + + g0 = (UInt32)(t = (UInt64)h0 + 5); + g1 = (UInt32)(t = (UInt64)h1 + (t >> 32)); + g2 = (UInt32)(t = (UInt64)h2 + (t >> 32)); + g3 = (UInt32)(t = (UInt64)h3 + (t >> 32)); + g4 = h4 + (UInt32)(t >> 32); + + mask = 0 - (g4 >> 2); + g0 &= mask; g1 &= mask; + g2 &= mask; g3 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; + h3 = (h3 & mask) | g3; + + h0 = (UInt32)(t = (UInt64)h0 + _n[0]); + h1 = (UInt32)(t = (UInt64)h1 + (t >> 32) + _n[1]); + h2 = (UInt32)(t = (UInt64)h2 + (t >> 32) + _n[2]); + h3 = (UInt32)(t = (UInt64)h3 + (t >> 32) + _n[3]); + + SetUi32(tag, h0); + SetUi32(tag + 4, h1); + SetUi32(tag + 8, h2); + SetUi32(tag + 12, h3); +} + +void CBaseCoder::DeriveKey() +{ + NXChaCha20::XHChaCha20Block_Core(_derivedKey, _key.Key, _nonce); + ComputePolyKey(); + _poly1305.SetKey(_polyKey); + if (_aadSize > 0) + { + _poly1305.UpdateAad(_aad, _aadSize); + } + _derivedKeyValid = true; +} + +Z7_COM7F_IMF(CBaseCoder::Init()) +{ + COM_TRY_BEGIN + + PrepareKey(); + _counter = 1; + _blockPos = kBlockSize; + _derivedKeyValid = false; + _poly1305.Reset(); + + return S_OK; + + COM_TRY_END +} + +#ifndef Z7_EXTRACT_ONLY + +Z7_COM7F_IMF(CEncoder::ResetInitVector()) +{ + for (unsigned i = 0; i < sizeof(_nonce); i++) + _nonce[i] = 0; + MY_RAND_GEN(_nonce, kNonceSize); + _counter = 1; + _blockPos = kBlockSize; + _derivedKeyValid = false; + _poly1305.Reset(); + + _aadSize = 1; + const unsigned nonceSizeMinus1 = kNonceSize - 1; + const unsigned nonceHigh = (nonceSizeMinus1 >= 16) ? (1 << 6) : 0; + const unsigned nonceLow = nonceSizeMinus1 & 0x0F; + _aad[0] = (Byte)(_key.NumCyclesPower + | (_key.SaltSize == 0 ? 0 : (1 << 7)) + | nonceHigh); + if (_key.SaltSize != 0) + { + _aad[1] = (Byte)(((_key.SaltSize - 1) << 4) | nonceLow); + memcpy(_aad + 2, _key.Salt, _key.SaltSize); + _aadSize = 2 + _key.SaltSize; + memcpy(_aad + _aadSize, _nonce, kNonceSize); + _aadSize += kNonceSize; + } + else + { + _aad[1] = (Byte)(nonceLow); + _aadSize = 2; + memcpy(_aad + _aadSize, _nonce, kNonceSize); + _aadSize += kNonceSize; + } + + _tagReady = false; + _propsWritten = false; + memset(_computedTag, 0, kTagSize); + return S_OK; +} + +Z7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size)) +{ + ProcessData(data, size); + _poly1305.Update(data, size); + return size; +} + +Z7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) +{ + Byte props[2 + sizeof(_key.Salt) + kNonceSize + kTagSize]; + unsigned propsSize = 1; + + const unsigned nonceSizeMinus1 = kNonceSize - 1; + const unsigned nonceHigh = (nonceSizeMinus1 >= 16) ? (1 << 6) : 0; + const unsigned nonceLow = nonceSizeMinus1 & 0x0F; + + props[0] = (Byte)(_key.NumCyclesPower + | (_key.SaltSize == 0 ? 0 : (1 << 7)) + | nonceHigh); + + if (_key.SaltSize != 0) + { + props[1] = (Byte)( + ((_key.SaltSize - 1) << 4) + | nonceLow); + memcpy(props + 2, _key.Salt, _key.SaltSize); + propsSize = 2 + _key.SaltSize; + memcpy(props + propsSize, _nonce, kNonceSize); + propsSize += kNonceSize; + } + else + { + props[1] = (Byte)(nonceLow); + propsSize = 2; + memcpy(props + propsSize, _nonce, kNonceSize); + propsSize += kNonceSize; + } + + if (!_tagReady) + { + if (!_derivedKeyValid && _propsWritten) + DeriveKey(); + if (_derivedKeyValid) + { + _poly1305.Final(_computedTag); + _tagReady = true; + } + else + { + memset(_computedTag, 0, kTagSize); + } + } + _propsWritten = true; + + memcpy(props + propsSize, _computedTag, kTagSize); + propsSize += kTagSize; + + return WriteStream(outStream, props, propsSize); +} + +CEncoder::CEncoder() +{ + _key.NumCyclesPower = 19; + _counter = 1; + _blockPos = kBlockSize; + _derivedKeyValid = false; + _aadSize = 0; + _tagReady = false; + _propsWritten = false; + memset(_computedTag, 0, kTagSize); +} + +#endif + +CDecoder::CDecoder() +{ + _counter = 1; + _blockPos = kBlockSize; + _derivedKeyValid = false; + _aadSize = 0; + _authChecked = false; + _authResult = 0; + memset(_expectedTag, 0, kTagSize); +} + +Z7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size)) +{ + if (!_derivedKeyValid) + DeriveKey(); + _poly1305.Update(data, size); + ProcessData(data, size); + return size; +} + +Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)) +{ + _key.ClearProps(); + + _counter = 1; + _blockPos = kBlockSize; + _derivedKeyValid = false; + _poly1305.Reset(); + _authChecked = false; + _authResult = 0; + memset(_expectedTag, 0, kTagSize); + + for (unsigned i = 0; i < sizeof(_nonce); i++) + _nonce[i] = 0; + + if (size == 0) + return S_OK; + + const unsigned b0 = data[0]; + _key.NumCyclesPower = b0 & 0x3F; + if ((b0 & 0xC0) == 0) + return size == 1 ? S_OK : E_INVALIDARG; + if (size <= 1) + return E_INVALIDARG; + + const unsigned b1 = data[1]; + const unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4); + const unsigned nonceSizeMinus1 = ((b0 >> 6) & 1) * 16 + (b1 & 0x0F); + const unsigned nonceSize = nonceSizeMinus1 + 1; + + const unsigned totalSize = 2 + saltSize + nonceSize + kTagSize; + + if (size != totalSize) + { + return E_INVALIDARG; + } + + _aadSize = totalSize - kTagSize; + memcpy(_aad, data, _aadSize); + + _key.SaltSize = saltSize; + data += 2; + for (unsigned i = 0; i < saltSize; i++) + _key.Salt[i] = *data++; + for (unsigned i = 0; i < nonceSize && i < kNonceSize; i++) + _nonce[i] = *data++; + + memcpy(_expectedTag, data, kTagSize); + + return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX + || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL; +} + +Z7_COM7F_IMF(CDecoder::CryptoAuthVerify(Int32 *result)) +{ + if (_authChecked) + { + *result = _authResult; + return S_OK; + } + _authChecked = true; + if (!_derivedKeyValid) + DeriveKey(); + + Byte computedTag[kTagSize]; + _poly1305.Final(computedTag); + + { + volatile Byte diff = 0; + for (unsigned i = 0; i < kTagSize; i++) + diff |= computedTag[i] ^ _expectedTag[i]; + _authResult = (diff == 0) ? 0 : 1; + } + *result = _authResult; + + Z7_memset_0_ARRAY(computedTag); + return S_OK; +} + +}} \ No newline at end of file diff --git a/CPP/7zip/Crypto/XChaCha20Poly1305.h b/CPP/7zip/Crypto/XChaCha20Poly1305.h new file mode 100644 index 00000000..bb402ad4 --- /dev/null +++ b/CPP/7zip/Crypto/XChaCha20Poly1305.h @@ -0,0 +1,117 @@ +// XChaCha20Poly1305.h +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#ifndef ZIP7_INC_CRYPTO_XCHACHA20_POLY1305_H +#define ZIP7_INC_CRYPTO_XCHACHA20_POLY1305_H + +#include "../../Common/MyCom.h" + +#include "../ICoder.h" +#include "../IPassword.h" + +#include "XChaCha20.h" + +namespace NCrypto { +namespace NXChaCha20Poly1305 { + +using NXChaCha20::kNonceSize; +using NXChaCha20::k_NumCyclesPower_Supported_MAX; + +const unsigned kTagSize = 16; +const unsigned kPolyKeySize = 32; + +class CPoly1305 +{ + UInt32 _r[4]; + UInt32 _s[4]; + UInt32 _h[5]; + UInt32 _n[4]; + Byte _block[16]; + unsigned _blockPos; + UInt64 _totalLen; + bool _finalized; + Byte _aadBlock[16]; + unsigned _aadBlockPos; + UInt64 _aadLen; + + void PadAndProcessBlock(Byte *buf, unsigned bufPos); + void ProcessBlocks(Byte *buf, unsigned &bufPos, UInt64 &len, const Byte *data, UInt32 size); +public: + CPoly1305(); + void SetKey(const Byte *key); + void Update(const Byte *data, UInt32 size); + void UpdateAad(const Byte *data, UInt32 size); + void Final(Byte *tag); + void Reset(); +}; + +class CBaseCoder: + public NXChaCha20::CBaseCoder +{ + Z7_COM7F_IMP(Init()) +protected: + virtual ~CBaseCoder() + { + Z7_memset_0_ARRAY(_polyKey); + Z7_memset_0_ARRAY(_aad); + } + + Byte _polyKey[kPolyKeySize]; + CPoly1305 _poly1305; + Byte _aad[2 + 16 + kNonceSize]; + unsigned _aadSize; + + void DeriveKey() override; + void ComputePolyKey(); +}; + +#ifndef Z7_EXTRACT_ONLY + +class CEncoder Z7_final: + public CBaseCoder, + public ICompressWriteCoderProperties, + public ICryptoResetInitVector +{ + Z7_COM_UNKNOWN_IMP_4( + ICompressFilter, + ICryptoSetPassword, + ICompressWriteCoderProperties, + ICryptoResetInitVector) + Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties) + Z7_IFACE_COM7_IMP(ICryptoResetInitVector) + + Byte _computedTag[kTagSize]; + bool _tagReady; + bool _propsWritten; + Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) +public: + CEncoder(); +}; + +#endif + +class CDecoder Z7_final: + public CBaseCoder, + public ICompressSetDecoderProperties2, + public ICryptoAuthVerify +{ + Z7_COM_UNKNOWN_IMP_4( + ICompressFilter, + ICryptoSetPassword, + ICompressSetDecoderProperties2, + ICryptoAuthVerify) + Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2) + Z7_IFACE_COM7_IMP(ICryptoAuthVerify) + + Byte _expectedTag[kTagSize]; + bool _authChecked; + Int32 _authResult; + Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size)) +public: + CDecoder(); +}; + +}} + +#endif \ No newline at end of file diff --git a/CPP/7zip/Crypto/XChaCha20Poly1305Register.cpp b/CPP/7zip/Crypto/XChaCha20Poly1305Register.cpp new file mode 100644 index 00000000..75bbdc1f --- /dev/null +++ b/CPP/7zip/Crypto/XChaCha20Poly1305Register.cpp @@ -0,0 +1,19 @@ +// XChaCha20Poly1305Register.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "XChaCha20Poly1305.h" + +namespace NCrypto { +namespace NXChaCha20Poly1305 { + +REGISTER_FILTER_E(XChaCha20Poly1305, + CDecoder, + CEncoder, + 0x6F10703, "XChaCha20-Poly1305") + +}} diff --git a/CPP/7zip/Crypto/XChaCha20Register.cpp b/CPP/7zip/Crypto/XChaCha20Register.cpp new file mode 100644 index 00000000..f429cfb2 --- /dev/null +++ b/CPP/7zip/Crypto/XChaCha20Register.cpp @@ -0,0 +1,19 @@ +// XChaCha20Register.cpp +// Copyright (C) fzxx Contributor: https://github.com/fzxx +// License: GNU LGPL v2.1+ + +#include "StdAfx.h" + +#include "../Common/RegisterCodec.h" + +#include "XChaCha20.h" + +namespace NCrypto { +namespace NXChaCha20 { + +REGISTER_FILTER_E(XChaCha20, + CDecoder, + CEncoder, + 0x6F10702, "XChaCha20") + +}} diff --git a/CPP/7zip/IPassword.h b/CPP/7zip/IPassword.h index 689f08cb..963ad648 100644 --- a/CPP/7zip/IPassword.h +++ b/CPP/7zip/IPassword.h @@ -50,5 +50,9 @@ CryptoGetTextPassword2() x(CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)) Z7_IFACE_CONSTR_PASSWORD(ICryptoGetTextPassword2, 0x11) +#define Z7_IFACEM_ICryptoAuthVerify(x) \ + x(CryptoAuthVerify(Int32 *result)) +Z7_IFACE_CONSTR_PASSWORD(ICryptoAuthVerify, 0x12) + Z7_PURE_INTERFACES_END #endif diff --git a/CPP/7zip/Sha512.mak b/CPP/7zip/Sha512.mak new file mode 100644 index 00000000..f251dee3 --- /dev/null +++ b/CPP/7zip/Sha512.mak @@ -0,0 +1,6 @@ +COMMON_OBJS = $(COMMON_OBJS) \ + $O\Sha512Prepare.obj + +C_OBJS = $(C_OBJS) \ + $O\Sha512.obj \ + $O\Sha512Opt.obj diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp index 903cde22..265b9430 100644 --- a/CPP/7zip/UI/Agent/AgentOut.cpp +++ b/CPP/7zip/UI/Agent/AgentOut.cpp @@ -497,6 +497,7 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream, updatePairs.Add(up2); } CUpdatePair2 up2; + up2.Construct(); up2.NewData = up2.NewProps = true; up2.UseArcProps = false; up2.DirIndex = 0; diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index d04ddabf..c8edd193 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -233,11 +233,26 @@ void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive) } } + +void CProxyArc::FreeFiles() +{ + const unsigned numFiles = NumFiles; + NumFiles = 0; + CProxyFile *f = Files; + for (unsigned i = 0; i < numFiles; i++, f++) + if (f->NeedDeleteName) + delete [](wchar_t *)(void *)f->Name; + delete []Files; + Files = NULL; +} + +static const UInt32 k_NumFiles_Max = 0x7fffffff - 15; + HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) { // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { - Files.Free(); + FreeFiles(); Dirs.Clear(); Dirs.AddNew(); @@ -245,11 +260,15 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)) + if (numItems > k_NumFiles_Max) + return E_OUTOFMEMORY; if (progress) RINOK(progress->SetTotal(numItems)) - Files.Alloc(numItems); + Z7_ARRAY_NEW(Files, CProxyFile, numItems) + memset(Files, 0, (size_t)numItems * sizeof(*Files)); + NumFiles = numItems; UString path; UString name; @@ -375,6 +394,7 @@ HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress) RINOK(Archive_IsItem_Dir(archive, i, isDir)) CProxyFile &f = Files[i]; + f.Construct(); // optional because memset() in code above f.NameLen = len - namePos; s += namePos; @@ -579,6 +599,19 @@ bool CProxyArc2::IsThere_SubDir(unsigned dirIndex, const UString &name) const return false; } + +void CProxyArc2::FreeFiles() +{ + const unsigned numFiles = NumFiles; + NumFiles = 0; + CProxyFile2 *f = Files; + for (unsigned i = 0; i < numFiles; i++, f++) + if (f->NeedDeleteName) + delete [](wchar_t *)(void *)f->Name; + delete []Files; + Files = NULL; +} + HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) { if (!arc.GetRawProps) @@ -587,12 +620,14 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) { Dirs.Clear(); - Files.Free(); + FreeFiles(); IInArchive *archive = arc.Archive; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)) + if (numItems > k_NumFiles_Max) + return E_OUTOFMEMORY; if (progress) RINOK(progress->SetTotal(numItems)) UString fileName; @@ -609,7 +644,9 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) dir.PathPrefix = ':'; } - Files.Alloc(numItems); + Z7_ARRAY_NEW(Files, CProxyFile2, numItems) + memset(Files, 0, (size_t)numItems * sizeof(*Files)); + NumFiles = numItems; UString tempUString; AString tempAString; @@ -619,11 +656,12 @@ HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress) { if (progress && (i & 0xFFFFF) == 0) { - UInt64 currentItemIndex = i; + const UInt64 currentItemIndex = i; RINOK(progress->SetCompleted(¤tItemIndex)) } CProxyFile2 &file = Files[i]; + file.Construct(); const void *p; UInt32 size; diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h index c24dd914..c6736a81 100644 --- a/CPP/7zip/UI/Agent/AgentProxy.h +++ b/CPP/7zip/UI/Agent/AgentProxy.h @@ -11,8 +11,12 @@ struct CProxyFile unsigned NameLen; bool NeedDeleteName; - CProxyFile(): Name(NULL), NameLen(0), NeedDeleteName(false) {} - ~CProxyFile() { if (NeedDeleteName) delete [](wchar_t *)(void *)Name; } // delete [](wchar_t *)Name; + void Construct() + { + Name = NULL; + NameLen = 0; + NeedDeleteName = false; + } }; const unsigned k_Proxy_RootDirIndex = 0; @@ -47,9 +51,14 @@ class CProxyArc void CalculateSizes(unsigned dirIndex, IInArchive *archive); unsigned AddDir(unsigned dirIndex, int arcIndex, const UString &name); + void FreeFiles(); public: CObjectVector Dirs; // Dirs[0] - root - CObjArray Files; // all items from archive in same order + CProxyFile *Files; // all items from archive in same order + unsigned NumFiles; + + CProxyArc(): Files(NULL), NumFiles(0) {} + ~CProxyArc() { FreeFiles(); } // returns index in Dirs[], or -1, int FindSubDir(unsigned dirIndex, const wchar_t *name) const; @@ -83,17 +92,17 @@ struct CProxyFile2 int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; } bool IsDir() const { return DirIndex != -1; } - CProxyFile2(): - DirIndex(-1), AltDirIndex(-1), Parent(-1), - Name(NULL), NameLen(0), - NeedDeleteName(false), - Ignore(false), - IsAltStream(false) - {} - ~CProxyFile2() + + void Construct() { - if (NeedDeleteName) - delete [](wchar_t *)(void *)Name; + DirIndex = -1; + AltDirIndex = -1; + Parent = -1; + Name = NULL; + NameLen = 0; + NeedDeleteName = false; + Ignore = false; + IsAltStream = false; } }; @@ -110,8 +119,6 @@ struct CProxyDir2 UInt32 NumSubFiles; CProxyDir2(): ArcIndex(-1) {} - void AddFileSubItem(UInt32 index, const UString &name); - void Clear(); }; const unsigned k_Proxy2_RootDirIndex = k_Proxy_RootDirIndex; @@ -123,10 +130,15 @@ class CProxyArc2 void CalculateSizes(unsigned dirIndex, IInArchive *archive); // AddRealIndices_of_Dir DOES NOT ADD item itself represented by dirIndex void AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const; + void FreeFiles(); public: CObjectVector Dirs; // Dirs[0] - root folder // Dirs[1] - for alt streams of root dir - CObjArray Files; // all items from archive in same order + CProxyFile2 *Files; // all items from archive in same order + unsigned NumFiles; + + CProxyArc2(): Files(NULL), NumFiles(0) {} + ~CProxyArc2() { FreeFiles(); } bool IsThere_SubDir(unsigned dirIndex, const UString &name) const; diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index 6631629a..7f6da0ce 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -1842,6 +1842,11 @@ Z7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre outStreamLoc = new CStdOutFileStream; else { + if (_isSplit) + { + RINOK(PrepareOperation(askExtractMode)) + return SetOperationResult(NArchive::NExtract::NOperationResult::kUnsupportedMethod); + } bool needExit = true; RINOK(GetExtractStream(outStreamLoc, needExit)) if (needExit) @@ -2674,6 +2679,7 @@ Z7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes)) { COM_TRY_BEGIN + // if (_isSplit) opRes = NArchive::NExtract::NOperationResult::kUnsupportedMethod; // printf("\nCArchiveExtractCallback::SetOperationResult: %d %s\n", opRes, GetAnsiString(_diskFilePath)); #ifndef Z7_SFX diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp index e71158cf..c944ee93 100644 --- a/CPP/7zip/UI/Common/LoadCodecs.cpp +++ b/CPP/7zip/UI/Common/LoadCodecs.cpp @@ -211,10 +211,11 @@ static FString GetBaseFolderPrefixFromRegistry() && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kFormatsFolderName)) { FString path; - if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path)) return path; - if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path; - if (ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path)) return path; - if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) return path; + if ( ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPath2Value, path) + || ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path) + || ReadPathFromRegistry(HKEY_CURRENT_USER, kProgramPathValue, path) + || ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue, path)) + moduleFolderPrefix = path; } #endif diff --git a/CPP/7zip/UI/Common/UpdatePair.cpp b/CPP/7zip/UI/Common/UpdatePair.cpp index 99b0aafb..8fc56159 100644 --- a/CPP/7zip/UI/Common/UpdatePair.cpp +++ b/CPP/7zip/UI/Common/UpdatePair.cpp @@ -196,6 +196,7 @@ void GetUpdatePairInfoList( while (dirIndex < numDirItems || arcIndex < numArcItems) { CUpdatePair pair; + pair.Construct(); int dirIndex2 = -1; int arcIndex2 = -1; diff --git a/CPP/7zip/UI/Common/UpdatePair.h b/CPP/7zip/UI/Common/UpdatePair.h index 13228b0e..a2855c41 100644 --- a/CPP/7zip/UI/Common/UpdatePair.h +++ b/CPP/7zip/UI/Common/UpdatePair.h @@ -15,7 +15,7 @@ struct CUpdatePair int DirIndex; int HostIndex; // >= 0 for alt streams only, contains index of host pair - CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {} + void Construct() { ArcIndex = -1; DirIndex = -1; HostIndex = -1; } }; void GetUpdatePairInfoList( diff --git a/CPP/7zip/UI/Common/UpdateProduce.cpp b/CPP/7zip/UI/Common/UpdateProduce.cpp index 88d25015..9b66d36e 100644 --- a/CPP/7zip/UI/Common/UpdateProduce.cpp +++ b/CPP/7zip/UI/Common/UpdateProduce.cpp @@ -19,6 +19,7 @@ void UpdateProduce( const CUpdatePair &pair = updatePairs[i]; CUpdatePair2 up2; + up2.Construct(); up2.DirIndex = pair.DirIndex; up2.ArcIndex = pair.ArcIndex; up2.NewData = up2.NewProps = true; diff --git a/CPP/7zip/UI/Common/UpdateProduce.h b/CPP/7zip/UI/Common/UpdateProduce.h index 9db6c1e4..3d163815 100644 --- a/CPP/7zip/UI/Common/UpdateProduce.h +++ b/CPP/7zip/UI/Common/UpdateProduce.h @@ -19,28 +19,28 @@ struct CUpdatePair2 bool IsMainRenameItem; bool IsSameTime; + void Construct() + { + NewData = false; + NewProps = false; + UseArcProps = false; + IsAnti = false; + DirIndex = -1; + ArcIndex = -1; + NewNameIndex = -1; + IsMainRenameItem = false; + IsSameTime = false; + } + void SetAs_NoChangeArcItem(unsigned arcIndex) // int { - NewData = NewProps = false; + Construct(); UseArcProps = true; - IsAnti = false; ArcIndex = (int)arcIndex; } bool ExistOnDisk() const { return DirIndex != -1; } bool ExistInArchive() const { return ArcIndex != -1; } - - CUpdatePair2(): - NewData(false), - NewProps(false), - UseArcProps(false), - IsAnti(false), - DirIndex(-1), - ArcIndex(-1), - NewNameIndex(-1), - IsMainRenameItem(false), - IsSameTime(false) - {} }; Z7_PURE_INTERFACES_BEGIN diff --git a/CPP/7zip/UI/Far/FarUtils.cpp b/CPP/7zip/UI/Far/FarUtils.cpp index 3c33d8eb..1d331e95 100644 --- a/CPP/7zip/UI/Far/FarUtils.cpp +++ b/CPP/7zip/UI/Far/FarUtils.cpp @@ -8,7 +8,7 @@ #ifndef UNDER_CE #include "../../../Windows/Console.h" #endif -#include "../../../Windows/Defs.h" +#include "../../../Windows/WinDefs.h" #include "../../../Windows/ErrorMsg.h" #include "FarUtils.h" @@ -259,17 +259,15 @@ void CStartupInfo::SetRegKeyValue(HKEY parentKey, const char *keyName, regKey.SetValue(valueName, value); } +/* CSysString CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, const CSysString &valueDefault) const { - NRegistry::CKey regKey; - if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS) - return valueDefault; - CSysString value; - if (regKey.QueryValue(valueName, value) != ERROR_SUCCESS) - return valueDefault; - + NRegistry::CKey regKey; + if (OpenRegKey(parentKey, keyName, regKey) != ERROR_SUCCESS + || regKey.QueryValue(valueName, value) != ERROR_SUCCESS) + value = valueDefault; return value; } @@ -286,6 +284,7 @@ UInt32 CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName, return value; } +*/ bool CStartupInfo::QueryRegKeyValue(HKEY parentKey, const char *keyName, LPCTSTR valueName, bool valueDefault) const diff --git a/CPP/7zip/UI/Far/Plugin.cpp b/CPP/7zip/UI/Far/Plugin.cpp index b7f91d69..f04f712e 100644 --- a/CPP/7zip/UI/Far/Plugin.cpp +++ b/CPP/7zip/UI/Far/Plugin.cpp @@ -143,8 +143,13 @@ void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex) panelItem.Reserved[1] = 0; } + +static const UInt32 k_NumFiles_Max = 0x7fffffff - 15; + int CPlugin::GetFindData(PluginPanelItem **panelItems, int *itemsNumber, int opMode) { + *panelItems = NULL; + *itemsNumber = 0; // CScreenRestorer screenRestorer; if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0) { @@ -160,8 +165,13 @@ int CPlugin::GetFindData(PluginPanelItem **panelItems, int *itemsNumber, int opM } UInt32 numItems; - _folder->GetNumberOfItems(&numItems); - *panelItems = new PluginPanelItem[numItems]; + if (_folder->GetNumberOfItems(&numItems) != S_OK) + return FALSE; + if (numItems > k_NumFiles_Max) + return FALSE; + + Z7_ARRAY_NEW(*panelItems, PluginPanelItem, numItems) + memset(*panelItems, 0, (size_t)numItems * sizeof(PluginPanelItem)); try { for (UInt32 i = 0; i < numItems; i++) @@ -174,6 +184,7 @@ int CPlugin::GetFindData(PluginPanelItem **panelItems, int *itemsNumber, int opM catch(...) { delete [](*panelItems); + *panelItems = NULL; throw; } *itemsNumber = (int)numItems; diff --git a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp index 9f083c56..f8bfcb5f 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp @@ -95,15 +95,16 @@ struct CBrowseItem UInt32 NumRootItems; UInt64 Size; - CBrowseItem(): - // MainFileIndex(0), - SubFileIndex(-1), - WasInterrupted(false), - NumFiles(0), - NumDirs(0), - NumRootItems(0), - Size(0) - {} + void Construct() + { + // MainFileIndex = 0; + SubFileIndex = -1; + WasInterrupted = false; + NumFiles = 0; + NumDirs = 0; + NumRootItems = 0; + Size = 0; + } }; @@ -114,6 +115,10 @@ struct CBrowseEnumerator CFileInfo fi_SubFile; CBrowseItem bi; + CBrowseEnumerator() + { + bi.Construct(); + } void Enumerate(unsigned level); bool NeedInterrupt() const { @@ -1504,6 +1509,7 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s if (d.Len() < 2 || d.Back() != '\\') return E_FAIL; CBrowseItem item; + item.Construct(); item.MainFileIndex = files.Size(); CFileInfo &fi = files.AddNew(); fi.SetAsDir(); @@ -1552,6 +1558,7 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s } } CBrowseItem item; + item.Construct(); item.MainFileIndex = files.Size(); item.Size = fi.Size; files.Add(fi); diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 53e56fe2..4baca7bb 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -1725,8 +1725,33 @@ void CCompressDialog::SetEncryptionMethod() const CArcInfoEx &ai = Get_ArcInfoEx(); if (ai.Is_7z()) { + const int index = FindRegistryFormat(ai.Name); + UString encryptionMethod; + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + encryptionMethod = fo.EncryptionMethod; + encryptionMethod.RemoveChar(L'-'); + encryptionMethod.RemoveChar(L'+'); + encryptionMethod.MakeLower_Ascii(); + } ComboBox_AddStringAscii(_encryptionMethod, "AES-256"); - _encryptionMethod.SetCurSel(0); + ComboBox_AddStringAscii(_encryptionMethod, "XChaCha20"); + ComboBox_AddStringAscii(_encryptionMethod, "XChaCha20-Poly1305"); + ComboBox_AddStringAscii(_encryptionMethod, "AES+XChaCha20-Poly1305"); + ComboBox_AddStringAscii(_encryptionMethod, "AES+XChaCha20+Ascon"); + int sel = 0; + if (encryptionMethod.IsEqualTo_Ascii_NoCase("xchacha20poly1305")) + sel = 2; + else if (encryptionMethod.IsEqualTo_Ascii_NoCase("xchacha20")) + sel = 1; + else if (encryptionMethod.IsEqualTo_Ascii_NoCase("aesxchacha20poly1305") || encryptionMethod.IsEqualTo_Ascii_NoCase("axp")) + sel = 3; + else if (encryptionMethod.IsEqualTo_Ascii_NoCase("aesxchacha20ascon") || encryptionMethod.IsEqualTo_Ascii_NoCase("axa")) + sel = 4; + else if (encryptionMethod.IsEqualTo_Ascii_NoCase("aes256")) + sel = 0; + _encryptionMethod.SetCurSel(sel); _default_encryptionMethod_Index = 0; } else if (ai.Is_Zip()) @@ -1810,11 +1835,11 @@ bool CCompressDialog::IsMethodEqualTo(const UString &s) UString CCompressDialog::GetEncryptionMethodSpec() { UString s; - if (_encryptionMethod.GetCount() > 0 - && _encryptionMethod.GetCurSel() != _default_encryptionMethod_Index) + if (_encryptionMethod.GetCount() > 0) { _encryptionMethod.GetText(s); s.RemoveChar(L'-'); + s.RemoveChar(L'+'); } return s; } diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index df1516c3..a1888dd1 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc @@ -136,8 +136,8 @@ BEGIN CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, g4x2, yPsw + 79, g4xs2, 10 - LTEXT "&Encryption method:", IDT_COMPRESS_ENCRYPTION_METHOD, g4x2, yPsw + 95, 100, 8 - COMBOBOX IDC_COMPRESS_ENCRYPTION_METHOD, g4x2 + 100, yPsw + 93, g4xs2 - 100, 198, MY_COMBO + LTEXT "&Encryption method:", IDT_COMPRESS_ENCRYPTION_METHOD, g4x2, yPsw + 95, 70, 8 + COMBOBOX IDC_COMPRESS_ENCRYPTION_METHOD, g4x2 + 70, yPsw + 93, g4xs2 - 70, 198, MY_COMBO CONTROL "Encrypt file &names", IDX_COMPRESS_ENCRYPT_FILE_NAMES, MY_CHECKBOX, g4x2, yPsw + 111, g4xs2, 10 diff --git a/CPP/Build.mak b/CPP/Build.mak index d9fcfb52..409420da 100644 --- a/CPP/Build.mak +++ b/CPP/Build.mak @@ -164,6 +164,9 @@ LFLAGS = $(LFLAGS) /FIXED:NO !IF "$(PLATFORM)" == "arm64" # we can get better compression ratio with ARM64 filter if we change alignment to 4096 # LFLAGS = $(LFLAGS) /FILEALIGN:4096 +# ARM64 MSVC compiler doesn't suppress C4746 even with /volatile:ms flag, +# so we explicitly disable warning 4746 (volatile in /volatile:iso mode) +CFLAGS = $(CFLAGS) -wd4746 !ENDIF !IFNDEF DEF_FILE diff --git a/CPP/Common/Common0.h b/CPP/Common/Common0.h index 5781a957..a6b842da 100644 --- a/CPP/Common/Common0.h +++ b/CPP/Common/Common0.h @@ -162,7 +162,7 @@ if compiled with new GCC libstdc++, GCC libstdc++ can use: So we can use Z7_ARRAY_NEW macro instead of new[] operator. */ #if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64) - #define Z7_ARRAY_NEW(p, T, size) p = new T[((size) > 0xFFFFFFFFu / sizeof(T)) ? 0xFFFFFFFFu / sizeof(T) : (size)]; + #define Z7_ARRAY_NEW(p, T, size) p = new T[((size) > (0xFFFFFFFFu - 0x7fu) / sizeof(T)) ? (0xFFFFFFFFu - 0x7fu) / sizeof(T) : (size)]; #else #define Z7_ARRAY_NEW(p, T, size) p = new T[size]; #endif diff --git a/CPP/Windows/Clipboard.cpp b/CPP/Windows/Clipboard.cpp index bc7e201d..d39c2646 100644 --- a/CPP/Windows/Clipboard.cpp +++ b/CPP/Windows/Clipboard.cpp @@ -9,7 +9,7 @@ #include "../Common/StringConvert.h" #include "Clipboard.h" -#include "Defs.h" +#include "WinDefs.h" #include "MemoryGlobal.h" #include "Shell.h" diff --git a/CPP/Windows/CommonDialog.cpp b/CPP/Windows/CommonDialog.cpp index 7a92d5f9..2e3f297b 100644 --- a/CPP/Windows/CommonDialog.cpp +++ b/CPP/Windows/CommonDialog.cpp @@ -13,7 +13,7 @@ #endif #include "CommonDialog.h" -#include "Defs.h" +#include "WinDefs.h" // #include "FileDir.h" #ifndef _UNICODE diff --git a/CPP/Windows/Console.h b/CPP/Windows/Console.h index 818b8d43..6b494c84 100644 --- a/CPP/Windows/Console.h +++ b/CPP/Windows/Console.h @@ -3,7 +3,7 @@ #ifndef ZIP7_INC_WINDOWS_CONSOLE_H #define ZIP7_INC_WINDOWS_CONSOLE_H -#include "Defs.h" +#include "WinDefs.h" namespace NWindows { namespace NConsole { diff --git a/CPP/Windows/Control/ImageList.h b/CPP/Windows/Control/ImageList.h index 688f1777..c10eea7b 100644 --- a/CPP/Windows/Control/ImageList.h +++ b/CPP/Windows/Control/ImageList.h @@ -5,7 +5,7 @@ #include -#include "../Defs.h" +#include "../WinDefs.h" namespace NWindows { namespace NControl { diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h index 944bca2b..9ae11159 100644 --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h @@ -13,8 +13,6 @@ #include "../Common/MyString.h" #include "../Common/MyWindows.h" -#include "Defs.h" - #include "FileIO.h" namespace NWindows { diff --git a/CPP/Windows/FileIO.h b/CPP/Windows/FileIO.h index 26edef43..a202df5d 100644 --- a/CPP/Windows/FileIO.h +++ b/CPP/Windows/FileIO.h @@ -31,7 +31,7 @@ #include "../Windows/TimeUtils.h" -#include "Defs.h" +#include "WinDefs.h" HRESULT GetLastError_noZero_HRESULT(); diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp index b4023060..6cb98086 100644 --- a/CPP/Windows/FileSystem.cpp +++ b/CPP/Windows/FileSystem.cpp @@ -9,7 +9,7 @@ #endif #include "FileSystem.h" -#include "Defs.h" +#include "WinDefs.h" #ifndef _UNICODE extern bool g_IsNT; diff --git a/CPP/Windows/Menu.h b/CPP/Windows/Menu.h index e1de4c4b..00aa692f 100644 --- a/CPP/Windows/Menu.h +++ b/CPP/Windows/Menu.h @@ -6,7 +6,7 @@ #include "../Common/MyWindows.h" #include "../Common/MyString.h" -#include "Defs.h" +#include "WinDefs.h" namespace NWindows { diff --git a/CPP/Windows/ProcessUtils.h b/CPP/Windows/ProcessUtils.h index b1fce3ae..34fef8da 100644 --- a/CPP/Windows/ProcessUtils.h +++ b/CPP/Windows/ProcessUtils.h @@ -39,7 +39,7 @@ typedef PROCESS_MEMORY_COUNTERS *PPROCESS_MEMORY_COUNTERS; #include "../Common/MyString.h" -#include "Defs.h" +#include "WinDefs.h" #include "Handle.h" namespace NWindows { diff --git a/CPP/Windows/PropVariantConv.cpp b/CPP/Windows/PropVariantConv.cpp index 21a7b4e3..467c0f8f 100644 --- a/CPP/Windows/PropVariantConv.cpp +++ b/CPP/Windows/PropVariantConv.cpp @@ -4,7 +4,7 @@ #include "../Common/IntToString.h" -#include "Defs.h" +#include "WinDefs.h" #include "PropVariantConv.h" #define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; } diff --git a/CPP/Windows/SecurityUtils.h b/CPP/Windows/SecurityUtils.h index 022a8f37..9775d095 100644 --- a/CPP/Windows/SecurityUtils.h +++ b/CPP/Windows/SecurityUtils.h @@ -9,7 +9,7 @@ #include #endif -#include "Defs.h" +#include "WinDefs.h" #ifndef _UNICODE diff --git a/CPP/Windows/Shell.h b/CPP/Windows/Shell.h index 9e58e25c..163c7d9a 100644 --- a/CPP/Windows/Shell.h +++ b/CPP/Windows/Shell.h @@ -12,7 +12,7 @@ #include "../Common/MyString.h" -#include "Defs.h" +#include "WinDefs.h" namespace NWindows { namespace NShell { diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h index 1df84d32..25764b8e 100644 --- a/CPP/Windows/Synchronization.h +++ b/CPP/Windows/Synchronization.h @@ -7,7 +7,7 @@ #include "../Common/MyTypes.h" -#include "Defs.h" +#include "WinDefs.h" #ifdef _WIN32 #include "Handle.h" diff --git a/CPP/Windows/Thread.h b/CPP/Windows/Thread.h index 75c16160..028267bc 100644 --- a/CPP/Windows/Thread.h +++ b/CPP/Windows/Thread.h @@ -5,7 +5,7 @@ #include "../../C/Threads.h" -#include "Defs.h" +#include "WinDefs.h" namespace NWindows { diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp index 4e3bc590..c83f75d6 100644 --- a/CPP/Windows/TimeUtils.cpp +++ b/CPP/Windows/TimeUtils.cpp @@ -7,8 +7,8 @@ #include #endif -#include "Defs.h" #include "TimeUtils.h" +#include "WinDefs.h" namespace NWindows { namespace NTime { diff --git a/CPP/Windows/Defs.h b/CPP/Windows/WinDefs.h similarity index 83% rename from CPP/Windows/Defs.h rename to CPP/Windows/WinDefs.h index 8ab9cf5e..86512d28 100644 --- a/CPP/Windows/Defs.h +++ b/CPP/Windows/WinDefs.h @@ -1,7 +1,7 @@ // Windows/Defs.h -#ifndef ZIP7_INC_WINDOWS_DEFS_H -#define ZIP7_INC_WINDOWS_DEFS_H +#ifndef ZIP7_INC_WINDOWS_WIN_DEFS_H +#define ZIP7_INC_WINDOWS_WIN_DEFS_H #include "../Common/MyWindows.h" diff --git a/CPP/Windows/Window.h b/CPP/Windows/Window.h index a99143bd..b0ddef9f 100644 --- a/CPP/Windows/Window.h +++ b/CPP/Windows/Window.h @@ -6,7 +6,7 @@ #include "../Common/MyWindows.h" #include "../Common/MyString.h" -#include "Defs.h" +#include "WinDefs.h" #ifndef UNDER_CE #ifdef WM_CHANGEUISTATE diff --git a/DOC/7zip.wxs b/DOC/7zip.wxs index 9ec9cf94..44e71e19 100644 --- a/DOC/7zip.wxs +++ b/DOC/7zip.wxs @@ -1,7 +1,7 @@ - + diff --git a/DOC/Methods.txt b/DOC/Methods.txt index 3e5707c7..11bc9bcc 100644 --- a/DOC/Methods.txt +++ b/DOC/Methods.txt @@ -1,8 +1,8 @@ 7-Zip method IDs for 7z and xz archives --------------------------------------- -Version: 24.02 -Date: 2024-03-22 +Version: 26.01 +Date: 2026-06-12 Each compression or crypto method in 7z is associated with unique binary value (ID). The length of ID in bytes is arbitrary but it can not exceed 63 bits (8 bytes). @@ -170,7 +170,11 @@ List of defined IDs 03 - Rar29AES (AES-128 + modified SHA-1) 07 - [7z] - 01 - 7zAES (AES-256 + SHA-256) + 01 - 7zAES (AES-256-CBC + SHA-256) + 02 - XChaCha20 (SHA-256) + 03 - XChaCha20-Poly1305 (SHA-256) + 04 - AES-256-CTR + XChaCha20-Poly1305 (PBKDF2-SHA512 + HKDF-BLAKE2sp) + 05 - AES-256-CTR + XChaCha20 + Ascon (PBKDF2-SHA512 + HKDF-BLAKE2sp) --- diff --git a/DOC/readme.txt b/DOC/readme.txt index e0048cfe..fd01e3b8 100644 --- a/DOC/readme.txt +++ b/DOC/readme.txt @@ -1,4 +1,4 @@ -7-Zip 26.01 Sources +7-Zip 26.02 Sources ------------------- 7-Zip is a file archiver for Windows. diff --git a/DOC/src-history.txt b/DOC/src-history.txt index 8f507b0d..7858175f 100644 --- a/DOC/src-history.txt +++ b/DOC/src-history.txt @@ -1,6 +1,11 @@ HISTORY of the 7-Zip source code -------------------------------- +26.02 2026-06-25 +------------------------- +- Some bugs and vulnerabilities were fixed. + + 26.01 2026-04-27 ------------------------- - linux version of 7-Zip can use huge pages (2 MB pages). It can increase compression