Update src/core/crypto/xts_encryption_layer.cpp
This commit is contained in:
parent
f62bdd3bb6
commit
c720675be0
1 changed files with 37 additions and 55 deletions
|
|
@ -20,67 +20,49 @@ std::size_t XTSEncryptionLayer::Read(u8* data, std::size_t length, std::size_t o
|
|||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
constexpr std::size_t PrefetchSectors = 4;
|
||||
|
||||
auto* out = data;
|
||||
std::size_t remaining = length;
|
||||
std::size_t current_offset = offset;
|
||||
std::size_t total_read = 0;
|
||||
// Handle initial unaligned part within a sector.
|
||||
if (auto const sector_offset = offset % XTS_SECTOR_SIZE; sector_offset != 0) {
|
||||
const std::size_t aligned_off = offset - sector_offset;
|
||||
std::array<u8, XTS_SECTOR_SIZE> block{};
|
||||
if (auto const got = base->Read(block.data(), XTS_SECTOR_SIZE, aligned_off); got > 0) {
|
||||
if (got < XTS_SECTOR_SIZE)
|
||||
std::memset(block.data() + got, 0, XTS_SECTOR_SIZE - got);
|
||||
cipher.XTSTranscode(block.data(), XTS_SECTOR_SIZE, block.data(), aligned_off / XTS_SECTOR_SIZE,
|
||||
XTS_SECTOR_SIZE, Op::Decrypt);
|
||||
|
||||
auto const to_copy = std::min<std::size_t>(length, got > sector_offset ? got - sector_offset : 0);
|
||||
if (to_copy > 0) {
|
||||
std::memcpy(data, block.data() + sector_offset, to_copy);
|
||||
data += to_copy;
|
||||
offset += to_copy;
|
||||
length -= to_copy;
|
||||
total_read += to_copy;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
std::array<u8, XTS_SECTOR_SIZE> sector{};
|
||||
|
||||
if (length > 0) {
|
||||
// Process aligned middle inplace, in sector sized multiples.
|
||||
while (length >= XTS_SECTOR_SIZE) {
|
||||
const std::size_t req = (length / XTS_SECTOR_SIZE) * XTS_SECTOR_SIZE;
|
||||
const std::size_t got = base->Read(data, req, offset);
|
||||
if (got == 0) {
|
||||
while (remaining > 0) {
|
||||
const std::size_t sector_index = current_offset / XTS_SECTOR_SIZE;
|
||||
const std::size_t sector_offset = current_offset % XTS_SECTOR_SIZE;
|
||||
|
||||
const std::size_t sectors_to_read = std::min<std::size_t>(PrefetchSectors,
|
||||
(remaining + sector_offset +
|
||||
XTS_SECTOR_SIZE - 1) /
|
||||
XTS_SECTOR_SIZE);
|
||||
|
||||
for (std::size_t s = 0; s < sectors_to_read && remaining > 0; ++s) {
|
||||
const std::size_t index = sector_index + s;
|
||||
const std::size_t read_offset = index * XTS_SECTOR_SIZE;
|
||||
const std::size_t got = base->Read(sector.data(), XTS_SECTOR_SIZE, read_offset);
|
||||
if (got == 0)
|
||||
return total_read;
|
||||
}
|
||||
const std::size_t got_rounded = got - (got % XTS_SECTOR_SIZE);
|
||||
if (got_rounded > 0) {
|
||||
cipher.XTSTranscode(data, got_rounded, data, offset / XTS_SECTOR_SIZE, XTS_SECTOR_SIZE, Op::Decrypt);
|
||||
data += got_rounded;
|
||||
offset += got_rounded;
|
||||
length -= got_rounded;
|
||||
total_read += got_rounded;
|
||||
}
|
||||
// If we didn't get a full sector next, break to handle tail.
|
||||
if (got_rounded != got) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Handle tail within a sector, if any.
|
||||
if (length > 0) {
|
||||
std::array<u8, XTS_SECTOR_SIZE> block{};
|
||||
const std::size_t got = base->Read(block.data(), XTS_SECTOR_SIZE, offset);
|
||||
if (got > 0) {
|
||||
if (got < XTS_SECTOR_SIZE) {
|
||||
std::memset(block.data() + got, 0, XTS_SECTOR_SIZE - got);
|
||||
}
|
||||
cipher.XTSTranscode(block.data(), XTS_SECTOR_SIZE, block.data(),
|
||||
offset / XTS_SECTOR_SIZE, XTS_SECTOR_SIZE, Op::Decrypt);
|
||||
const std::size_t to_copy = std::min<std::size_t>(length, got);
|
||||
std::memcpy(data, block.data(), to_copy);
|
||||
|
||||
if (got < XTS_SECTOR_SIZE)
|
||||
std::memset(sector.data() + got, 0, XTS_SECTOR_SIZE - got);
|
||||
|
||||
cipher.XTSTranscode(sector.data(), XTS_SECTOR_SIZE, sector.data(), index, XTS_SECTOR_SIZE,
|
||||
Op::Decrypt);
|
||||
|
||||
const std::size_t local_offset = (s == 0) ? sector_offset : 0;
|
||||
const std::size_t available = XTS_SECTOR_SIZE - local_offset;
|
||||
const std::size_t to_copy = std::min<std::size_t>(available, remaining);
|
||||
std::memcpy(out, sector.data() + local_offset, to_copy);
|
||||
|
||||
out += to_copy;
|
||||
current_offset += to_copy;
|
||||
remaining -= to_copy;
|
||||
total_read += to_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total_read;
|
||||
}
|
||||
} // namespace Core::Crypto
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue