void CData::CryptBlock(Byte *buf, bool encrypt) { Byte inBuf[16]; UInt32 A, B, C, D, T, TA, TB; A = GetUi32(buf + 0) ^ Keys[0]; B = GetUi32(buf + 4) ^ Keys[1]; C = GetUi32(buf + 8) ^ Keys[2]; D = GetUi32(buf + 12) ^ Keys[3]; if (!encrypt) memcpy(inBuf, buf, sizeof(inBuf)); for (int i = 0; i < kNumRounds; i++) { UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3]; T = ((C + rotlFixed(D, 11)) ^ key); TA = A ^ SubstLong(T); T = ((D ^ rotlFixed(C, 17)) + key); TB = B ^ SubstLong(T); A = C; B = D; C = TA; D = TB; } SetUi32(buf + 0, C ^ Keys[0]); SetUi32(buf + 4, D ^ Keys[1]); SetUi32(buf + 8, A ^ Keys[2]); SetUi32(buf + 12, B ^ Keys[3]); UpdateKeys(encrypt ? buf : inBuf); }
UInt32 MY_FAST_CALL AesCbcDecode(CAesCbc *cbc, Byte *data, UInt32 size) { UInt32 i; UInt32 in[4], out[4]; if (size == 0) return 0; if (size < AES_BLOCK_SIZE) return AES_BLOCK_SIZE; size -= AES_BLOCK_SIZE; for (i = 0; i <= size; i += AES_BLOCK_SIZE, data += AES_BLOCK_SIZE) { in[0] = GetUi32(data); in[1] = GetUi32(data + 4); in[2] = GetUi32(data + 8); in[3] = GetUi32(data + 12); AesDecode32(in, out, cbc->aes.rkey, cbc->aes.numRounds2); SetUi32(data, cbc->prev[0] ^ out[0]); SetUi32(data + 4, cbc->prev[1] ^ out[1]); SetUi32(data + 8, cbc->prev[2] ^ out[2]); SetUi32(data + 12, cbc->prev[3] ^ out[3]); cbc->prev[0] = in[0]; cbc->prev[1] = in[1]; cbc->prev[2] = in[2]; cbc->prev[3] = in[3]; } return i; }
SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size) { if (size == 0) return 0; if (size < AES_BLOCK_SIZE) return AES_BLOCK_SIZE; size -= AES_BLOCK_SIZE; SizeT i; UInt32 in[4], out[4]; for (i = 0; i <= size; i += AES_BLOCK_SIZE, data += AES_BLOCK_SIZE) { in[0] = GetUi32(data); in[1] = GetUi32(data + 4); in[2] = GetUi32(data + 8); in[3] = GetUi32(data + 12); AesDecode32(out, in, p->aes.rkey, p->aes.numRounds2); SetUi32(data, p->prev[0] ^ out[0]); SetUi32(data + 4, p->prev[1] ^ out[1]); SetUi32(data + 8, p->prev[2] ^ out[2]); SetUi32(data + 12, p->prev[3] ^ out[3]); p->prev[0] = in[0]; p->prev[1] = in[1]; p->prev[2] = in[2]; p->prev[3] = in[3]; } return i; }
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) { Byte *p; const Byte *lim; size &= ~(size_t)3; ip += 4; p = data; lim = data + size; if (encoding) for (;;) { for (;;) { if (p >= lim) return p - data; p += 4; if (p[-1] == 0xEB) break; } { UInt32 v = GetUi32(p - 4); v <<= 2; v += ip + (UInt32)(p - data); v >>= 2; v &= 0x00FFFFFF; v |= 0xEB000000; SetUi32(p - 4, v); } } for (;;) { for (;;) { if (p >= lim) return p - data; p += 4; if (p[-1] == 0xEB) break; } { UInt32 v = GetUi32(p - 4); v <<= 2; v -= ip + (UInt32)(p - data); v >>= 2; v &= 0x00FFFFFF; v |= 0xEB000000; SetUi32(p - 4, v); } } }
static Bool FindSignature(CSzFile *stream, UInt64 *resPos) { Byte buf[kBufferSize]; size_t numPrevBytes = 0; *resPos = 0; for (;;) { size_t processed, pos; if (*resPos > kSignatureSearchLimit) return False; processed = kBufferSize - numPrevBytes; if (File_Read(stream, buf + numPrevBytes, &processed) != 0) return False; processed += numPrevBytes; if (processed < k7zStartHeaderSize || (processed == k7zStartHeaderSize && numPrevBytes != 0)) return False; processed -= k7zStartHeaderSize; for (pos = 0; pos <= processed; pos++) { for (; pos <= processed && buf[pos] != '7'; pos++); if (pos > processed) break; if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) { *resPos += pos; return True; } } *resPos += processed; numPrevBytes = k7zStartHeaderSize; memmove(buf, buf + processed, k7zStartHeaderSize); } }
HRESULT CCabBlockInStream::PreRead(ISequentialInStream *stream, UInt32 &packSize, UInt32 &unpackSize) { const UInt32 kHeaderSize = 8; const UInt32 kReservedMax = 256; Byte header[kHeaderSize + kReservedMax]; RINOK(ReadStream_FALSE(stream, header, kHeaderSize + ReservedSize)) packSize = GetUi16(header + 4); unpackSize = GetUi16(header + 6); if (packSize > kBlockSize - _size) return S_FALSE; RINOK(ReadStream_FALSE(stream, _buf + _size, packSize)); if (MsZip) { if (_size == 0) { if (packSize < 2 || _buf[0] != 0x43 || _buf[1] != 0x4B) return S_FALSE; _pos = 2; } if (_size + packSize > ((UInt32)1 << 15) + 12) /* v9.31 fix. MSZIP specification */ return S_FALSE; } if (GetUi32(header) != 0) // checkSum if (CheckSum(header, kHeaderSize + ReservedSize) != CheckSum(_buf + _size, packSize)) return S_FALSE; _size += packSize; return S_OK; }
HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize) { Byte temp[4]; RINOK(ReadStream_FALSE(inStream, temp, 2)); _ivSize = GetUi16(temp); if (_ivSize == 0) { memset(_iv, 0, 16); SetUi32(_iv + 0, crc); SetUi64(_iv + 4, unpackSize); _ivSize = 12; } else if (_ivSize == 16) { RINOK(ReadStream_FALSE(inStream, _iv, _ivSize)); } else return E_NOTIMPL; RINOK(ReadStream_FALSE(inStream, temp, 4)); _remSize = GetUi32(temp); const UInt32 kAlign = 16; if (_remSize < 16 || _remSize > (1 << 18)) return E_NOTIMPL; if (_remSize + kAlign > _buf.Size()) { _buf.Alloc(_remSize + kAlign); _bufAligned = (Byte *)((ptrdiff_t)((Byte *)_buf + kAlign - 1) & ~(ptrdiff_t)(kAlign - 1)); } return ReadStream_FALSE(inStream, _bufAligned, _remSize); }
HRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize) { Byte temp[4]; RINOK(ReadStream_FALSE(inStream, temp, 2)); _ivSize = GetUi16(temp); if (_ivSize == 0) { memset(_iv, 0, 16); SetUi32(_iv + 0, crc); SetUi64(_iv + 4, unpackSize); _ivSize = 12; } else if (_ivSize == 16) { RINOK(ReadStream_FALSE(inStream, _iv, _ivSize)); } else return E_NOTIMPL; RINOK(ReadStream_FALSE(inStream, temp, 4)); _remSize = GetUi32(temp); // const UInt32 kAlign = 16; if (_remSize < 16 || _remSize > (1 << 18)) return E_NOTIMPL; if (_remSize > _bufAligned.Size()) { _bufAligned.AllocAtLeast(_remSize); if (!(Byte *)_bufAligned) return E_OUTOFMEMORY; } return ReadStream_FALSE(inStream, _bufAligned, _remSize); }
static inline bool TestSignature(const Byte *p) { for (int i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; return CrcCalc(p + 12, 20) == GetUi32(p + 8); }
void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks) { for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) { p[0] ^= GetUi32(data); p[1] ^= GetUi32(data + 4); p[2] ^= GetUi32(data + 8); p[3] ^= GetUi32(data + 12); Aes_Encode(p + 4, p, p); SetUi32(data, p[0]); SetUi32(data + 4, p[1]); SetUi32(data + 8, p[2]); SetUi32(data + 12, p[3]); } }
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CPpmd7 ppmd; CByteInToLook s; SRes res = SZ_OK; s.p.Read = ReadByte; s.inStream = inStream; s.begin = s.end = s.cur = NULL; s.extra = False; s.res = SZ_OK; s.processed = 0; if (coder->Props.size != 5) return SZ_ERROR_UNSUPPORTED; { unsigned order = coder->Props.data[0]; UInt32 memSize = GetUi32(coder->Props.data + 1); if (order < PPMD7_MIN_ORDER || order > PPMD7_MAX_ORDER || memSize < PPMD7_MIN_MEM_SIZE || memSize > PPMD7_MAX_MEM_SIZE) return SZ_ERROR_UNSUPPORTED; Ppmd7_Construct(&ppmd); if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) return SZ_ERROR_MEM; Ppmd7_Init(&ppmd, order); } { CPpmd7z_RangeDec rc; Ppmd7z_RangeDec_CreateVTable(&rc); rc.Stream = &s.p; if (!Ppmd7z_RangeDec_Init(&rc)) res = SZ_ERROR_DATA; else if (s.extra) res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); else { SizeT i; for (i = 0; i < outSize; i++) { int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); if (s.extra || sym < 0) break; outBuffer[i] = (Byte)sym; } if (i != outSize) res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) res = SZ_ERROR_DATA; } } Ppmd7_Free(&ppmd, allocMain); return res; }
static bool ParseInt64_MTime(const char *p, Int64 &val) { // rare case tar : ZEROs in Docker-Windows TARs // rare case tar : spaces if (GetUi32(p) != 0) for (unsigned i = 0; i < 12; i++) if (p[i] != ' ') return ParseInt64(p, val); val = 0; return true; }
static inline bool TestSignature2(const Byte *p) { int i; for (i = 0; i < kSignatureSize; i++) if (p[i] != kSignature[i]) return false; if (CrcCalc(p + 12, 20) == GetUi32(p + 8)) return true; for (i = 8; i < kHeaderSize; i++) if (p[i] != 0) return false; return (p[6] != 0 || p[7] != 0); }
API_FUNC_static_IsArc IsArc_Swfc(const Byte *p, size_t size) { if (size < kHeaderBaseSize + 2 + 1) // 2 + 1 (for zlib check) return k_IsArc_Res_NEED_MORE; if ((p[0] != SWF_COMPRESSED_ZLIB && p[0] != SWF_COMPRESSED_LZMA) || p[1] != 'W' || p[2] != 'S' || p[3] >= kVerLim) return k_IsArc_Res_NO; UInt32 uncompressedSize = GetUi32(p + 4); if (uncompressedSize > kFileSizeMax) return k_IsArc_Res_NO; if (p[0] == SWF_COMPRESSED_ZLIB) { if (!NCompress::NZlib::IsZlib_3bytes(p + 8)) return k_IsArc_Res_NO; } else { if (size < kHeaderLzmaSize + 2) return k_IsArc_Res_NEED_MORE; if (p[kHeaderLzmaSize] != 0 || (p[kHeaderLzmaSize + 1] & 0x80) != 0) return k_IsArc_Res_NO; UInt32 lzmaPackSize = GetUi32(p + 8); UInt32 lzmaProp = p[12]; UInt32 lzmaDicSize = GetUi32(p + 13); if (lzmaProp > 5 * 5 * 9 || lzmaDicSize > ((UInt32)1 << 28) || lzmaPackSize < 5 || lzmaPackSize > ((UInt32)1 << 28)) return k_IsArc_Res_NO; } return k_IsArc_Res_YES; }
void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks) { UInt32 in[4], out[4]; for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) { in[0] = GetUi32(data); in[1] = GetUi32(data + 4); in[2] = GetUi32(data + 8); in[3] = GetUi32(data + 12); Aes_Decode(p + 4, out, in); SetUi32(data, p[0] ^ out[0]); SetUi32(data + 4, p[1] ^ out[1]); SetUi32(data + 8, p[2] ^ out[2]); SetUi32(data + 12, p[3] ^ out[3]); p[0] = in[0]; p[1] = in[1]; p[2] = in[2]; p[3] = in[3]; } }
static UInt32 CheckSum(const Byte *p, UInt32 size) { UInt32 sum = 0; for (; size >= 8; size -= 8) { sum ^= GetUi32(p) ^ GetUi32(p + 4); p += 8; } if (size >= 4) { sum ^= GetUi32(p); p += 4; } size &= 3; if (size > 2) sum ^= (UInt32)(*p++) << 16; if (size > 1) sum ^= (UInt32)(*p++) << 8; if (size > 0) sum ^= (UInt32)(*p++); return sum; }
API_FUNC_static_IsArc IsArc_Swf(const Byte *p, size_t size) { if (size < kHeaderBaseSize) return k_IsArc_Res_NEED_MORE; if (p[0] != SWF_UNCOMPRESSED || p[1] != 'W' || p[2] != 'S' || p[3] >= kVerLim) return k_IsArc_Res_NO; UInt32 uncompressedSize = GetUi32(p + 4); if (uncompressedSize > kFileSizeMax) return k_IsArc_Res_NO; return k_IsArc_Res_YES; }
SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size) { SizeT i; if (size == 0) return 0; if (size < AES_BLOCK_SIZE) return AES_BLOCK_SIZE; size -= AES_BLOCK_SIZE; for (i = 0; i <= size; i += AES_BLOCK_SIZE, data += AES_BLOCK_SIZE) { p->prev[0] ^= GetUi32(data); p->prev[1] ^= GetUi32(data + 4); p->prev[2] ^= GetUi32(data + 8); p->prev[3] ^= GetUi32(data + 12); AesEncode32(p->prev, p->prev, p->aes.rkey, p->aes.numRounds2); SetUi32(data, p->prev[0]); SetUi32(data + 4, p->prev[1]); SetUi32(data + 8, p->prev[2]); SetUi32(data + 12, p->prev[3]); } return i; }
UInt32 MY_FAST_CALL AesCbcEncode(CAesCbc *cbc, Byte *data, UInt32 size) { UInt32 i; if (size == 0) return 0; if (size < AES_BLOCK_SIZE) return AES_BLOCK_SIZE; size -= AES_BLOCK_SIZE; for (i = 0; i <= size; i += AES_BLOCK_SIZE, data += AES_BLOCK_SIZE) { cbc->prev[0] ^= GetUi32(data); cbc->prev[1] ^= GetUi32(data + 4); cbc->prev[2] ^= GetUi32(data + 8); cbc->prev[3] ^= GetUi32(data + 12); AesEncode32(cbc->prev, cbc->prev, cbc->aes.rkey, cbc->aes.numRounds2); SetUi32(data, cbc->prev[0]); SetUi32(data + 4, cbc->prev[1]); SetUi32(data + 8, cbc->prev[2]); SetUi32(data + 12, cbc->prev[3]); } return i; }
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size) { if (size < 5) return E_INVALIDARG; _order = props[0]; UInt32 memSize = GetUi32(props + 1); if (_order < PPMD7_MIN_ORDER || _order > PPMD7_MAX_ORDER || memSize < PPMD7_MIN_MEM_SIZE || memSize > PPMD7_MAX_MEM_SIZE) return E_NOTIMPL; if (!_inStream.Alloc(1 << 20)) return E_OUTOFMEMORY; if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc)) return E_OUTOFMEMORY; return S_OK; }
static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc) { size_t i, numBlocks, crcStartPos, pos = 1; UInt32 crc; if (size < 5 || buf[0] != 0) return SZ_ERROR_ARCHIVE; size -= 4; crc = CrcCalc(buf, size); if (crc != GetUi32(buf + size)) return SZ_ERROR_ARCHIVE; { UInt64 numBlocks64; READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64); numBlocks = (size_t)numBlocks64; if (numBlocks != numBlocks64 || numBlocks * 2 > size) return SZ_ERROR_ARCHIVE; } crcStartPos = pos; Xz_Free(p, alloc); if (numBlocks != 0) { p->numBlocks = numBlocks; p->numBlocksAllocated = numBlocks; p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); if (p->blocks == 0) return SZ_ERROR_MEM; for (i = 0; i < numBlocks; i++) { CXzBlockSizes *block = &p->blocks[i]; READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize); READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize); if (block->totalSize == 0) return SZ_ERROR_ARCHIVE; } } while ((pos & 3) != 0) if (buf[pos++] != 0) return SZ_ERROR_ARCHIVE; return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; }
bool CExtraSubBlock::ExtractInfoZipUnicodePath(AString &name, AString &res) const { res.Empty(); if (ID != NFileHeader::NExtraID::kInfoZipUnicodePath || (UInt32)Data.Size() < 5 || *(const Byte *)Data < 1 || GetUi32((const Byte *)Data + 1) != CrcCalc(name, name.Len())) return false; int size = (int)Data.Size() - sizeof(short) * 2 - sizeof(Byte); if (size > 0) { char *p = res.GetBuffer(size + 1); memcpy(p, (const Byte *)Data + sizeof(short) * 2 + sizeof(Byte), size); p[size] = '\0'; res.ReleaseBuffer(); } return true; }
static Bool FindSignature(CInBuf *stream, UInt64 *resPos) { Byte buf[kBufferSize]; size_t numPrevBytes = 0; *resPos = 0; for (;;) { size_t numTests, pos; if (*resPos > kSignatureSearchLimit) return False; do { size_t processed = kBufferSize - numPrevBytes; if (InBuf_Read(stream, buf + numPrevBytes, &processed) != 0) return False; if (processed == 0) return False; numPrevBytes += processed; } while (numPrevBytes <= k7zStartHeaderSize); numTests = numPrevBytes - k7zStartHeaderSize; for (pos = 0; pos < numTests; pos++) { for (; buf[pos] != '7' && pos < numTests; pos++); if (pos == numTests) break; if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) { *resPos += pos; return True; } } *resPos += numTests; numPrevBytes -= numTests; memmove(buf, buf + numTests, numPrevBytes); } }
void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize) { unsigned i, wSize; wSize = keySize + 28; keySize /= 4; w[0] = ((UInt32)keySize / 2) + 3; w += 4; for (i = 0; i < keySize; i++, key += 4) w[i] = GetUi32(key); for (; i < wSize; i++) { UInt32 t = w[i - 1]; unsigned rem = i % keySize; if (rem == 0) t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]); else if (keySize > 6 && rem == 4) t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]); w[i] = w[i - keySize] ^ t; } }
static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc) { UInt64 indexSize; Byte buf[XZ_STREAM_FOOTER_SIZE]; if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE) return SZ_ERROR_NO_ARCHIVE; *startOffset = -XZ_STREAM_FOOTER_SIZE; RINOK(SeekFromCur(stream, startOffset)); RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) { UInt32 total = 0; *startOffset += XZ_STREAM_FOOTER_SIZE; for (;;) { size_t i; #define TEMP_BUF_SIZE (1 << 10) Byte tempBuf[TEMP_BUF_SIZE]; if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) return SZ_ERROR_NO_ARCHIVE; i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; total += (UInt32)i; *startOffset = -(Int64)i; RINOK(SeekFromCur(stream, startOffset)); RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE)); for (; i != 0; i--) if (tempBuf[i - 1] != 0) break; if (i != 0) { if ((i & 3) != 0) return SZ_ERROR_NO_ARCHIVE; *startOffset += i; break; } } if (*startOffset < XZ_STREAM_FOOTER_SIZE) return SZ_ERROR_NO_ARCHIVE; *startOffset -= XZ_STREAM_FOOTER_SIZE; RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) return SZ_ERROR_NO_ARCHIVE; } p->flags = (CXzStreamFlags)GetBe16(buf + 8); if (!XzFlags_IsSupported(p->flags)) return SZ_ERROR_UNSUPPORTED; if (GetUi32(buf) != CrcCalc(buf + 4, 6)) return SZ_ERROR_ARCHIVE; indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; *startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE); RINOK(SeekFromCur(stream, startOffset)); RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)); { UInt64 totalSize = Xz_GetPackSize(p); UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize; if (totalSize == XZ_SIZE_OVERFLOW || sum >= ((UInt64)1 << 63) || totalSize >= ((UInt64)1 << 63)) return SZ_ERROR_ARCHIVE; *startOffset = -(Int64)sum; RINOK(SeekFromCur(stream, startOffset)); } { CXzStreamFlags headerFlags; CSecToRead secToRead; SecToRead_CreateVTable(&secToRead); secToRead.realStream = stream; RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s)); return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; } }
void AesCbc_Init(CAesCbc *p, const Byte *iv) { unsigned i; for (i = 0; i < 4; i++) p->prev[i] = GetUi32(iv + i * 4); }
static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAllocPtr alloc) { UInt64 indexSize; Byte buf[XZ_STREAM_FOOTER_SIZE]; UInt64 pos = *startOffset; if ((pos & 3) != 0 || pos < XZ_STREAM_FOOTER_SIZE) return SZ_ERROR_NO_ARCHIVE; pos -= XZ_STREAM_FOOTER_SIZE; RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)); if (!XZ_FOOTER_SIG_CHECK(buf + 10)) { UInt32 total = 0; pos += XZ_STREAM_FOOTER_SIZE; for (;;) { size_t i; #define TEMP_BUF_SIZE (1 << 10) Byte temp[TEMP_BUF_SIZE]; i = (pos > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)pos; pos -= i; RINOK(LookInStream_SeekRead_ForArc(stream, pos, temp, i)); total += (UInt32)i; for (; i != 0; i--) if (temp[i - 1] != 0) break; if (i != 0) { if ((i & 3) != 0) return SZ_ERROR_NO_ARCHIVE; pos += i; break; } if (pos < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) return SZ_ERROR_NO_ARCHIVE; } if (pos < XZ_STREAM_FOOTER_SIZE) return SZ_ERROR_NO_ARCHIVE; pos -= XZ_STREAM_FOOTER_SIZE; RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf, XZ_STREAM_FOOTER_SIZE)); if (!XZ_FOOTER_SIG_CHECK(buf + 10)) return SZ_ERROR_NO_ARCHIVE; } p->flags = (CXzStreamFlags)GetBe16(buf + 8); if (!XzFlags_IsSupported(p->flags)) return SZ_ERROR_UNSUPPORTED; if (GetUi32(buf) != CrcCalc(buf + 4, 6)) return SZ_ERROR_ARCHIVE; indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; if (pos < indexSize) return SZ_ERROR_ARCHIVE; pos -= indexSize; RINOK(LookInStream_SeekTo(stream, pos)); RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)); { UInt64 totalSize = Xz_GetPackSize(p); if (totalSize == XZ_SIZE_OVERFLOW || totalSize >= ((UInt64)1 << 63) || pos < totalSize + XZ_STREAM_HEADER_SIZE) return SZ_ERROR_ARCHIVE; pos -= (totalSize + XZ_STREAM_HEADER_SIZE); RINOK(LookInStream_SeekTo(stream, pos)); *startOffset = pos; } { CXzStreamFlags headerFlags; CSecToRead secToRead; SecToRead_CreateVTable(&secToRead); secToRead.realStream = stream; RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt)); return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; } }
void AesCbc_Init(UInt32 *p, const Byte *iv) { unsigned i; for (i = 0; i < 4; i++) p[i] = GetUi32(iv + i * 4); }
static SRes SzArEx_Open2( CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) { uint8_t header[k7zStartHeaderSize]; int64_t startArcPos; uint64_t nextHeaderOffset, nextHeaderSize; size_t nextHeaderSizeT; uint32_t nextHeaderCRC; CBuf buffer; SRes res; startArcPos = 0; RINOK(inStream->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; nextHeaderOffset = GetUi64(header + 12); nextHeaderSize = GetUi64(header + 20); nextHeaderCRC = GetUi32(header + 28); p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) return SZ_ERROR_CRC; nextHeaderSizeT = (size_t)nextHeaderSize; if (nextHeaderSizeT != nextHeaderSize) return SZ_ERROR_MEM; if (nextHeaderSizeT == 0) return SZ_OK; if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) return SZ_ERROR_NO_ARCHIVE; { int64_t pos = 0; RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); if ((uint64_t)pos < startArcPos + nextHeaderOffset || (uint64_t)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || (uint64_t)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) return SZ_ERROR_INPUT_EOF; } RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) return SZ_ERROR_MEM; res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); if (res == SZ_OK) { res = SZ_ERROR_ARCHIVE; if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) { CSzData sd; uint64_t type; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); if (res == SZ_OK) { if (type == k7zIdEncodedHeader) { CBuf outBuffer; Buf_Init(&outBuffer); res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); if (res != SZ_OK) Buf_Free(&outBuffer, allocTemp); else { Buf_Free(&buffer, allocTemp); buffer.data = outBuffer.data; buffer.size = outBuffer.size; sd.Data = buffer.data; sd.Size = buffer.size; res = SzReadID(&sd, &type); } } } if (res == SZ_OK) { if (type == k7zIdHeader) res = SzReadHeader(p, &sd, allocMain, allocTemp); else res = SZ_ERROR_UNSUPPORTED; } } } Buf_Free(&buffer, allocTemp); return res; }
HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK) { passwOK = false; if (_remSize < 16) return E_NOTIMPL; Byte *p = _bufAligned; UInt16 format = GetUi16(p); if (format != 3) return E_NOTIMPL; UInt16 algId = GetUi16(p + 2); if (algId < kAES128) return E_NOTIMPL; algId -= kAES128; if (algId > 2) return E_NOTIMPL; UInt16 bitLen = GetUi16(p + 4); UInt16 flags = GetUi16(p + 6); if (algId * 64 + 128 != bitLen) return E_NOTIMPL; _key.KeySize = 16 + algId * 8; bool cert = ((flags & 2) != 0); if ((flags & 0x4000) != 0) { // Use 3DES for rd data return E_NOTIMPL; } if (cert) { return E_NOTIMPL; } else { if ((flags & 1) == 0) return E_NOTIMPL; } UInt32 rdSize = GetUi16(p + 8); if (rdSize + 16 > _remSize) return E_NOTIMPL; const unsigned kPadSize = kAesPadAllign; // is equal to blockSize of cipher for rd /* if (cert) { if ((rdSize & 0x7) != 0) return E_NOTIMPL; } else */ { // PKCS7 padding if (rdSize < kPadSize) return E_NOTIMPL; if ((rdSize & (kPadSize - 1)) != 0) return E_NOTIMPL; } memmove(p, p + 10, rdSize); const Byte *p2 = p + rdSize + 10; UInt32 reserved = GetUi32(p2); p2 += 4; /* if (cert) { UInt32 numRecipients = reserved; if (numRecipients == 0) return E_NOTIMPL; { UInt32 hashAlg = GetUi16(p2); hashAlg = hashAlg; UInt32 hashSize = GetUi16(p2 + 2); hashSize = hashSize; p2 += 4; reserved = reserved; // return E_NOTIMPL; for (unsigned r = 0; r < numRecipients; r++) { UInt32 specSize = GetUi16(p2); p2 += 2; p2 += specSize; } } } else */ { if (reserved != 0) return E_NOTIMPL; } UInt32 validSize = GetUi16(p2); p2 += 2; const size_t validOffset = p2 - p; if ((validSize & 0xF) != 0 || validOffset + validSize != _remSize) return E_NOTIMPL; { RINOK(SetKey(_key.MasterKey, _key.KeySize)); RINOK(SetInitVector(_iv, 16)); RINOK(Init()); Filter(p, rdSize); rdSize -= kPadSize; for (unsigned i = 0; i < kPadSize; i++) if (p[(size_t)rdSize + i] != kPadSize) return S_OK; // passwOK = false; } Byte fileKey[32]; NSha1::CContext sha; sha.Init(); sha.Update(_iv, _ivSize); sha.Update(p, rdSize); DeriveKey(sha, fileKey); RINOK(SetKey(fileKey, _key.KeySize)); RINOK(SetInitVector(_iv, 16)); Init(); memmove(p, p + validOffset, validSize); Filter(p, validSize); if (validSize < 4) return E_NOTIMPL; validSize -= 4; if (GetUi32(p + validSize) != CrcCalc(p, validSize)) return S_OK; passwOK = true; return S_OK; }