mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-25 22:54:17 +01:00
Lock decryption in CtrEncryptedBacking
This prevents a race where two threads could read at the same time and end up using the wrong IV leading to garbage data being read. This caused crashes in several games including Celeste.
This commit is contained in:
parent
ce0e032255
commit
31db70f1d4
@ -9,6 +9,7 @@
|
||||
namespace skyline::crypto {
|
||||
/**
|
||||
* @brief Wrapper for mbedtls for AES decryption using a cipher
|
||||
* @note The IV state must be appropriately locked during multi-threaded usage
|
||||
*/
|
||||
class AesCipher {
|
||||
private:
|
||||
|
@ -22,11 +22,14 @@ namespace skyline::vfs {
|
||||
|
||||
size_t sectorOffset{offset % SectorSize};
|
||||
if (sectorOffset == 0) {
|
||||
UpdateCtr(baseOffset + offset);
|
||||
size_t read{backing->Read(output, offset)};
|
||||
if (read != size)
|
||||
return 0;
|
||||
cipher.Decrypt(output);
|
||||
{
|
||||
std::lock_guard guard(mutex);
|
||||
UpdateCtr(baseOffset + offset);
|
||||
cipher.Decrypt(output);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -35,8 +38,11 @@ namespace skyline::vfs {
|
||||
size_t read{backing->Read(blockBuf, sectorStart)};
|
||||
if (read != SectorSize)
|
||||
return 0;
|
||||
UpdateCtr(baseOffset + sectorStart);
|
||||
cipher.Decrypt(blockBuf);
|
||||
{
|
||||
std::lock_guard guard(mutex);
|
||||
UpdateCtr(baseOffset + sectorStart);
|
||||
cipher.Decrypt(blockBuf);
|
||||
}
|
||||
if (size + sectorOffset < SectorSize) {
|
||||
std::memcpy(output.data(), blockBuf.data() + sectorOffset, size);
|
||||
return size;
|
||||
|
@ -16,6 +16,7 @@ namespace skyline::vfs {
|
||||
crypto::KeyStore::Key128 ctr;
|
||||
crypto::AesCipher cipher;
|
||||
std::shared_ptr<Backing> backing;
|
||||
std::mutex mutex; //!< Synchronize all AES-CTR cipher state modifications
|
||||
size_t baseOffset; //!< The offset of the backing into the file is used to calculate the IV
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user