EncryptedFileSystemCreator.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. using LibHac;
  2. using LibHac.Common;
  3. using LibHac.Fs;
  4. using LibHac.Fs.Fsa;
  5. using LibHac.FsSrv.FsCreator;
  6. using LibHac.FsSystem;
  7. namespace Ryujinx.HLE.FileSystem
  8. {
  9. public class EncryptedFileSystemCreator : IEncryptedFileSystemCreator
  10. {
  11. public EncryptedFileSystemCreator() { }
  12. public Result Create(out ReferenceCountedDisposable<IFileSystem> encryptedFileSystem, ReferenceCountedDisposable<IFileSystem> baseFileSystem,
  13. EncryptedFsKeyId keyId, in EncryptionSeed encryptionSeed)
  14. {
  15. UnsafeHelpers.SkipParamInit(out encryptedFileSystem);
  16. if (keyId < EncryptedFsKeyId.Save || keyId > EncryptedFsKeyId.CustomStorage)
  17. {
  18. return ResultFs.InvalidArgument.Log();
  19. }
  20. // Force all-zero keys for now since people can open the emulator with different keys or sd seeds sometimes
  21. var fs = new AesXtsFileSystem(baseFileSystem, new byte[0x32], 0x4000);
  22. var aesFileSystem = new ReferenceCountedDisposable<IFileSystem>(fs);
  23. // This wrapper will handle deleting files that were created with different keys
  24. var wrappedFs = new ChangedEncryptionHandlingFileSystem(aesFileSystem);
  25. encryptedFileSystem = new ReferenceCountedDisposable<IFileSystem>(wrappedFs);
  26. return Result.Success;
  27. }
  28. }
  29. public class ChangedEncryptionHandlingFileSystem : ForwardingFileSystem
  30. {
  31. public ChangedEncryptionHandlingFileSystem(ReferenceCountedDisposable<IFileSystem> baseFileSystem) : base(baseFileSystem) { }
  32. protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode)
  33. {
  34. UnsafeHelpers.SkipParamInit(out file);
  35. try
  36. {
  37. return base.DoOpenFile(out file, path, mode);
  38. }
  39. catch (HorizonResultException ex)
  40. {
  41. if (ResultFs.AesXtsFileHeaderInvalidKeys.Includes(ex.ResultValue))
  42. {
  43. Result rc = DeleteFile(path);
  44. if (rc.IsFailure()) return rc;
  45. return base.DoOpenFile(out file, path, mode);
  46. }
  47. throw;
  48. }
  49. }
  50. }
  51. }