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 > _bufAligned.Size()) { _bufAligned.AllocAtLeast(_remSize); if (!(Byte *)_bufAligned) return E_OUTOFMEMORY; } 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 + 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); }
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, uint16_t *dest) { size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; if (dest != 0) { size_t i; const uint8_t *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2); for (i = 0; i < len; i++) dest[i] = GetUi16(src + i * 2); } return len; }
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; }
bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage) { NWindows::NFile::NIO::CInFile file; if (!file.Open(fileName)) return false; UInt64 fileSize; if (!file.GetLength(fileSize)) return false; if (fileSize >= ((UInt32)1 << 31) - 32) return false; UString u; if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE) { if ((fileSize & 1) != 0) return false; CByteArr buf((size_t)fileSize); UInt32 processed; if (!file.Read(buf, (UInt32)fileSize, processed)) return false; if (processed != fileSize) return false; file.Close(); unsigned num = (unsigned)fileSize / 2; wchar_t *p = u.GetBuf(num); if (codePage == MY__CP_UTF16) for (unsigned i = 0; i < num; i++) { wchar_t c = GetUi16(buf + i * 2); if (c == 0) return false; p[i] = c; } else for (unsigned i = 0; i < num; i++) { wchar_t c = (wchar_t)GetBe16(buf + i * 2); if (c == 0) return false; p[i] = c; } p[num] = 0; u.ReleaseBuf_SetLen(num); } else { AString s; char *p = s.GetBuf((unsigned)fileSize); UInt32 processed; if (!file.Read(p, (UInt32)fileSize, processed)) return false; if (processed != fileSize) return false; file.Close(); s.ReleaseBuf_CalcLen((unsigned)processed); if (s.Len() != processed) return false; // #ifdef CP_UTF8 if (codePage == CP_UTF8) { if (!ConvertUTF8ToUnicode(s, u)) return false; } else // #endif MultiByteToUnicodeString2(u, s, codePage); } const wchar_t kGoodBOM = 0xFEFF; const wchar_t kBadBOM = 0xFFFE; UString s; unsigned i = 0; for (; i < u.Len() && u[i] == kGoodBOM; i++); for (; i < u.Len(); i++) { wchar_t c = u[i]; if (c == kGoodBOM || c == kBadBOM) return false; if (c == L'\n' || c == 0xD) { AddName(strings, s); s.Empty(); } else s += c; } AddName(strings, s); return true; }