From cd4530f29c6a4ffd1b023105350b0440fa63f47b Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 17 Aug 2021 10:46:52 -0700 Subject: [PATCH] Always use an all-zeros key for AES-XTS file systems (#2561) --- .../FileSystem/EncryptedFileSystemCreator.cs | 62 +++++++++++++++++++ Ryujinx.HLE/FileSystem/VirtualFileSystem.cs | 3 + 2 files changed, 65 insertions(+) create mode 100644 Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs diff --git a/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs b/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs new file mode 100644 index 0000000000..aaa8004467 --- /dev/null +++ b/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs @@ -0,0 +1,62 @@ +using LibHac; +using LibHac.Common; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.FsSrv.FsCreator; +using LibHac.FsSystem; + +namespace Ryujinx.HLE.FileSystem +{ + public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator + { + public EncryptedFileSystemCreator() { } + + public Result Create(out ReferenceCountedDisposable encryptedFileSystem, ReferenceCountedDisposable baseFileSystem, + EncryptedFsKeyId keyId, in EncryptionSeed encryptionSeed) + { + UnsafeHelpers.SkipParamInit(out encryptedFileSystem); + + if (keyId < EncryptedFsKeyId.Save || keyId > EncryptedFsKeyId.CustomStorage) + { + return ResultFs.InvalidArgument.Log(); + } + + // Force all-zero keys for now since people can open the emulator with different keys or sd seeds sometimes + var fs = new AesXtsFileSystem(baseFileSystem, new byte[0x32], 0x4000); + var aesFileSystem = new ReferenceCountedDisposable(fs); + + // This wrapper will handle deleting files that were created with different keys + var wrappedFs = new ChangedEncryptionHandlingFileSystem(aesFileSystem); + encryptedFileSystem = new ReferenceCountedDisposable(wrappedFs); + + return Result.Success; + } + } + + public class ChangedEncryptionHandlingFileSystem : ForwardingFileSystem + { + public ChangedEncryptionHandlingFileSystem(ReferenceCountedDisposable baseFileSystem) : base(baseFileSystem) { } + + protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode) + { + UnsafeHelpers.SkipParamInit(out file); + + try + { + return base.DoOpenFile(out file, path, mode); + } + catch (HorizonResultException ex) + { + if (ResultFs.AesXtsFileHeaderInvalidKeys.Includes(ex.ResultValue)) + { + Result rc = DeleteFile(path); + if (rc.IsFailure()) return rc; + + return base.DoOpenFile(out file, path, mode); + } + + throw; + } + } + } +} diff --git a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs index c4363f711d..1bd347656d 100644 --- a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs +++ b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs @@ -178,6 +178,9 @@ namespace Ryujinx.HLE.FileSystem DefaultFsServerObjects fsServerObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(serverBaseFs, KeySet, fsServer); + // Use our own encrypted fs creator that always uses all-zero keys + fsServerObjects.FsCreators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator(); + GameCard = fsServerObjects.GameCard; SdCard = fsServerObjects.SdCard;