aboutsummaryrefslogtreecommitdiff
path: root/src/core/crypto/xts_encryption_layer.cpp
diff options
context:
space:
mode:
authorgodpow <thesaviorsrule@yahoo.com>2025-10-26 02:12:27 +0100
committercrueter <crueter@eden-emu.dev>2025-10-26 02:12:27 +0100
commit41e15e95b19748f4c2da31e3b8263a8626ef306a (patch)
treeab8ff43ce407d9a72b3dd862b88058af367c27dd /src/core/crypto/xts_encryption_layer.cpp
parent73ebf59af77a81edee6c276a8c0f7e533a5948b2 (diff)
[crypto] Rework AES CTR/XTS streaming and squash heap churn (#2782)
AES Updates: Replaced heap churn with stack scratch buffers tail handling now stays in-place, no more recursive transcode detours. CTR/XTS modes read in larger, aligned chunks and still handle odd offsets cleanly. XTS prefetches a few sectors ahead to reduce extra reads. AesCtrStorage writer now uses the pooled buffer properly one stack slab, chunk forward, bump counter, repeat. Result: less malloc noise, fewer watchdog spikes at startup (though mbedtls still sets the pace). This should make the loading speed slightly better than before. Make sure to test. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2782 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: godpow <thesaviorsrule@yahoo.com> Co-committed-by: godpow <thesaviorsrule@yahoo.com>
Diffstat (limited to 'src/core/crypto/xts_encryption_layer.cpp')
-rw-r--r--src/core/crypto/xts_encryption_layer.cpp94
1 files changed, 38 insertions, 56 deletions
diff --git a/src/core/crypto/xts_encryption_layer.cpp b/src/core/crypto/xts_encryption_layer.cpp
index 240f930c57..5cfc67847d 100644
--- a/src/core/crypto/xts_encryption_layer.cpp
+++ b/src/core/crypto/xts_encryption_layer.cpp
@@ -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;
- }
- }
- 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) {
+ std::array<u8, XTS_SECTOR_SIZE> sector{};
+
+ 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);
- total_read += 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