From 5367d7c5cda1d9be118d8f905f23f86e738da4f8 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 5 Jan 2021 01:27:25 -0700 Subject: [PATCH] Add save data transfer sf interfaces --- src/LibHac/Boot/Package2StorageReader.cs | 2 +- src/LibHac/Crypto/KeyTypes.cs | 2 +- src/LibHac/Fs/Impl/SaveDataTransferTypes.cs | 54 +++++++++++++++++++ src/LibHac/Fs/SaveDataTransferTypes.cs | 33 ++++++++++++ src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs | 11 ++++ src/LibHac/FsSrv/Sf/ISaveDataChunkImporter.cs | 10 ++++ src/LibHac/FsSrv/Sf/ISaveDataChunkIterator.cs | 11 ++++ .../FsSrv/Sf/ISaveDataDivisionExporter.cs | 23 ++++++++ .../FsSrv/Sf/ISaveDataDivisionImporter.cs | 21 ++++++++ src/LibHac/FsSrv/Sf/ISaveDataExporter.cs | 14 +++++ src/LibHac/FsSrv/Sf/ISaveDataImporter.cs | 15 ++++++ .../FsSrv/Sf/ISaveDataTransferManager.cs | 14 +++++ .../Sf/ISaveDataTransferManagerForRepair.cs | 12 +++++ ...aveDataTransferManagerForSaveDataRepair.cs | 18 +++++++ .../ISaveDataTransferManagerWithDivision.cs | 23 ++++++++ .../FsSrv/Sf/ISaveDataTransferProhibiter.cs | 9 ++++ 16 files changed, 270 insertions(+), 2 deletions(-) create mode 100644 src/LibHac/Fs/Impl/SaveDataTransferTypes.cs create mode 100644 src/LibHac/Fs/SaveDataTransferTypes.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataChunkImporter.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataChunkIterator.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataDivisionExporter.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataDivisionImporter.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataExporter.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataImporter.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataTransferManager.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForRepair.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForSaveDataRepair.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataTransferManagerWithDivision.cs create mode 100644 src/LibHac/FsSrv/Sf/ISaveDataTransferProhibiter.cs diff --git a/src/LibHac/Boot/Package2StorageReader.cs b/src/LibHac/Boot/Package2StorageReader.cs index 9e53ad65..78b34710 100644 --- a/src/LibHac/Boot/Package2StorageReader.cs +++ b/src/LibHac/Boot/Package2StorageReader.cs @@ -21,7 +21,7 @@ namespace LibHac.Boot private IStorage _storage; private Package2Header _header; private KeySet _keySet; - private AesKey _key; + private Crypto.AesKey _key; public ref readonly Package2Header Header => ref _header; diff --git a/src/LibHac/Crypto/KeyTypes.cs b/src/LibHac/Crypto/KeyTypes.cs index a0efe4b1..a096778e 100644 --- a/src/LibHac/Crypto/KeyTypes.cs +++ b/src/LibHac/Crypto/KeyTypes.cs @@ -45,7 +45,7 @@ namespace LibHac.Crypto [FieldOffset(0)] private ulong _ulong; [FieldOffset(0)] public AesKey DataKey; - [FieldOffset(0)] public AesKey TweakKey; + [FieldOffset(0x10)] public AesKey TweakKey; public Span Data => SpanHelpers.CreateSpan(ref _byte, Size); public readonly ReadOnlySpan DataRo => SpanHelpers.CreateReadOnlySpan(in _byte, Size); diff --git a/src/LibHac/Fs/Impl/SaveDataTransferTypes.cs b/src/LibHac/Fs/Impl/SaveDataTransferTypes.cs new file mode 100644 index 00000000..ca6832f3 --- /dev/null +++ b/src/LibHac/Fs/Impl/SaveDataTransferTypes.cs @@ -0,0 +1,54 @@ +using System; +using System.Runtime.InteropServices; +using LibHac.Common; + +namespace LibHac.Fs.Impl +{ + [StructLayout(LayoutKind.Sequential, Size = 0x20)] + public struct InitialDataAad + { + public byte this[int i] + { + readonly get => BytesRo[i]; + set => Bytes[i] = value; + } + + public Span Bytes => SpanHelpers.AsByteSpan(ref this); + public readonly ReadOnlySpan BytesRo => SpanHelpers.AsReadOnlyByteSpan(in this); + } + + [StructLayout(LayoutKind.Sequential, Size = 0x10)] + public struct KeySeed + { + public byte this[int i] + { + readonly get => BytesRo[i]; + set => Bytes[i] = value; + } + + public Span Bytes => SpanHelpers.AsByteSpan(ref this); + public readonly ReadOnlySpan BytesRo => SpanHelpers.AsReadOnlyByteSpan(in this); + } + + [StructLayout(LayoutKind.Sequential, Size = 0x10)] + public struct InitialDataMac + { + public byte this[int i] + { + readonly get => BytesRo[i]; + set => Bytes[i] = value; + } + + public Span Bytes => SpanHelpers.AsByteSpan(ref this); + public readonly ReadOnlySpan BytesRo => SpanHelpers.AsReadOnlyByteSpan(in this); + } + + [StructLayout(LayoutKind.Sequential, Size = 0x20)] + public struct ImportReportInfo + { + public byte DiffChunkCount; + public byte DoubleDivisionDiffChunkCount; + public byte HalfDivisionDiffChunkCount; + public byte CompressionRate; + } +} diff --git a/src/LibHac/Fs/SaveDataTransferTypes.cs b/src/LibHac/Fs/SaveDataTransferTypes.cs new file mode 100644 index 00000000..e443d9b9 --- /dev/null +++ b/src/LibHac/Fs/SaveDataTransferTypes.cs @@ -0,0 +1,33 @@ +using System; +using System.Runtime.InteropServices; +using LibHac.Common; + +namespace LibHac.Fs +{ + [StructLayout(LayoutKind.Sequential, Size = 0x100)] + public struct RsaEncryptedKey + { + public byte this[int i] + { + readonly get => BytesRo[i]; + set => Bytes[i] = value; + } + + public Span Bytes => SpanHelpers.AsByteSpan(ref this); + public readonly ReadOnlySpan BytesRo => SpanHelpers.AsReadOnlyByteSpan(in this); + + } + + [StructLayout(LayoutKind.Sequential, Size = 0x10)] + public struct AesKey + { + public byte this[int i] + { + readonly get => BytesRo[i]; + set => Bytes[i] = value; + } + + public Span Bytes => SpanHelpers.AsByteSpan(ref this); + public readonly ReadOnlySpan BytesRo => SpanHelpers.AsReadOnlyByteSpan(in this); + } +} diff --git a/src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs new file mode 100644 index 00000000..4b66c019 --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataChunkExporter.cs @@ -0,0 +1,11 @@ +using System; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataChunkExporter : IDisposable + { + public Result Pull(out ulong bytesRead, OutBuffer buffer, ulong size); + public Result GetRestRawDataSize(out long remainingSize); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataChunkImporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataChunkImporter.cs new file mode 100644 index 00000000..4ac58f3c --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataChunkImporter.cs @@ -0,0 +1,10 @@ +using System; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataChunkImporter : IDisposable + { + public Result Push(InBuffer buffer, ulong size); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataChunkIterator.cs b/src/LibHac/FsSrv/Sf/ISaveDataChunkIterator.cs new file mode 100644 index 00000000..dea391b1 --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataChunkIterator.cs @@ -0,0 +1,11 @@ +using System; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataChunkIterator : IDisposable + { + public Result Next(); + public Result IsEnd(out bool isEnd); + public Result GetId(out uint chunkId); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataDivisionExporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataDivisionExporter.cs new file mode 100644 index 00000000..1523e51c --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataDivisionExporter.cs @@ -0,0 +1,23 @@ +using System; +using LibHac.Fs.Impl; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataDivisionExporter : IDisposable + { + public Result SetDivisionCount(int divisionCount); + public Result ReadSaveDataExtraData(OutBuffer extraData); + public Result OpenSaveDataDiffChunkIterator(out ReferenceCountedDisposable iterator); + public Result OpenSaveDataChunkExporter(out ReferenceCountedDisposable exporter, uint chunkId); + public Result CancelExport(); + public Result SuspendExport(OutBuffer exportContext); + public Result GetKeySeed(out KeySeed keySeed); + public Result GetInitialDataMac(out InitialDataMac initialDataMac); + public Result FinalizeExport(); + public Result GetInitialDataMacKeyGeneration(out int keyGeneration); + public Result GetImportInitialDataAad(out InitialDataAad initialDataAad); + public Result SetExportInitialDataAad(in InitialDataAad initialDataAad); + public Result GetReportInfo(out ImportReportInfo reportInfo); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataDivisionImporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataDivisionImporter.cs new file mode 100644 index 00000000..dc870f73 --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataDivisionImporter.cs @@ -0,0 +1,21 @@ +using System; +using LibHac.Fs.Impl; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataDivisionImporter : IDisposable + { + public Result ReadSaveDataExtraData(OutBuffer extraData); + public Result OpenSaveDataDiffChunkIterator(out ReferenceCountedDisposable iterator); + public Result InitializeImport(out long remaining, long sizeToProcess); + public Result FinalizeImport(); + public Result CancelImport(); + public Result GetImportContext(OutBuffer context); + public Result SuspendImport(); + public Result FinalizeImportWithoutSwap(); + public Result OpenSaveDataChunkImporter(out ReferenceCountedDisposable importer, uint chunkId); + public Result GetImportInitialDataAad(out InitialDataAad initialDataAad); + public Result GetReportInfo(out ImportReportInfo reportInfo); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataExporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataExporter.cs new file mode 100644 index 00000000..dfa498f0 --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataExporter.cs @@ -0,0 +1,14 @@ +using System; +using LibHac.Fs; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataExporter : IDisposable + { + public Result GetSaveDataInfo(out SaveDataInfo info); + public Result GetRestSize(out ulong remainingSize); + public Result Pull(out ulong bytesRead, OutBuffer buffer); + public Result PullInitialData(OutBuffer initialData); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataImporter.cs b/src/LibHac/FsSrv/Sf/ISaveDataImporter.cs new file mode 100644 index 00000000..289fd424 --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataImporter.cs @@ -0,0 +1,15 @@ +using System; +using LibHac.Fs; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataImporter : IDisposable + { + public Result GetSaveDataInfo(out SaveDataInfo info); + public Result GetRestSize(out ulong remainingSize); + public Result Push(InBuffer buffer); + // Can't name the method "Finalize" because it's basically a reserved method in .NET + public Result FinalizeImport(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataTransferManager.cs b/src/LibHac/FsSrv/Sf/ISaveDataTransferManager.cs new file mode 100644 index 00000000..268be16a --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataTransferManager.cs @@ -0,0 +1,14 @@ +using System; +using LibHac.Fs; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataTransferManager : IDisposable + { + public Result GetChallenge(OutBuffer challenge); + public Result SetToken(InBuffer token); + public Result OpenSaveDataExporter(out ReferenceCountedDisposable exporter, SaveDataSpaceId spaceId, ulong saveDataId); + public Result OpenSaveDataImporter(out ReferenceCountedDisposable importer, out long requiredSize, InBuffer initialData, in UserId userId, SaveDataSpaceId spaceId); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForRepair.cs b/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForRepair.cs new file mode 100644 index 00000000..338f7f2f --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForRepair.cs @@ -0,0 +1,12 @@ +using System; +using LibHac.Fs; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataTransferManagerForRepair : IDisposable + { + public Result OpenSaveDataExporter(out ReferenceCountedDisposable exporter, SaveDataSpaceId spaceId, ulong saveDataId); + public Result OpenSaveDataImporter(out ReferenceCountedDisposable importer, InBuffer initialData, SaveDataSpaceId spaceId); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForSaveDataRepair.cs b/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForSaveDataRepair.cs new file mode 100644 index 00000000..1b7a7bfa --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerForSaveDataRepair.cs @@ -0,0 +1,18 @@ +using System; +using LibHac.Fs; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataTransferManagerForSaveDataRepair : IDisposable + { + public Result GetChallenge(OutBuffer challenge); + public Result SetKeyPackage(InBuffer keyPackage); + public Result OpenSaveDataExporterAndGetEncryptedKey(out ReferenceCountedDisposable exporter, out RsaEncryptedKey key, SaveDataSpaceId spaceId, ulong saveDataId); + public Result PrepareOpenSaveDataImporter(out RsaEncryptedKey key); + public Result OpenSaveDataImporterForSaveDataAfterRepair(out ReferenceCountedDisposable importer, InBuffer initialDataBeforeRepair, InBuffer initialDataAfterRepair, UserId userId, SaveDataSpaceId spaceId); + public Result OpenSaveDataImporterForSaveDataBeforeRepair(out ReferenceCountedDisposable importer, InBuffer initialData, UserId userId, SaveDataSpaceId spaceId); + public Result OpenSaveDataExporterWithKey(out ReferenceCountedDisposable exporter, in AesKey key, SaveDataSpaceId spaceId, ulong saveDataId); + public Result OpenSaveDataImporterWithKey(out ReferenceCountedDisposable importer, in AesKey key, InBuffer initialData, UserId userId, ulong saveDataSpaceId); + } +} diff --git a/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerWithDivision.cs b/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerWithDivision.cs new file mode 100644 index 00000000..7c215bc8 --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataTransferManagerWithDivision.cs @@ -0,0 +1,23 @@ +using System; +using LibHac.Fs; +using LibHac.Sf; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataTransferManagerWithDivision : IDisposable + { + public Result GetChallenge(OutBuffer challenge); + public Result SetKeySeedPackage(InBuffer keySeedPackage); + public Result OpenSaveDataExporter(out ReferenceCountedDisposable exporter, SaveDataSpaceId spaceId, ulong saveDataId); + public Result OpenSaveDataExporterForDiffExport(out ReferenceCountedDisposable exporter, InBuffer initialData, SaveDataSpaceId spaceId, ulong saveDataId); + public Result OpenSaveDataExporterByContext(out ReferenceCountedDisposable exporter, InBuffer exportContext); + public Result OpenSaveDataImporterDeprecated(out ReferenceCountedDisposable importer, InBuffer initialData, in UserId userId, SaveDataSpaceId spaceId); + public Result OpenSaveDataImporterForDiffImport(out ReferenceCountedDisposable importer, InBuffer initialData, SaveDataSpaceId spaceId, ulong saveDataId); + public Result OpenSaveDataImporterForDuplicateDiffImport(out ReferenceCountedDisposable importer, InBuffer initialData, SaveDataSpaceId spaceId, ulong saveDataId); + public Result OpenSaveDataImporter(out ReferenceCountedDisposable importer, InBuffer initialData, in UserId userId, SaveDataSpaceId spaceId, bool useSwap); + public Result OpenSaveDataImporterByContext(out ReferenceCountedDisposable importer, InBuffer importContext); + public Result CancelSuspendingImport(Ncm.ApplicationId applicationId, in UserId userId); + public Result CancelSuspendingImportByAttribute(in SaveDataAttribute attribute); + public Result SwapSecondary(in SaveDataAttribute attribute, bool doSwap, long primaryCommitId); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Sf/ISaveDataTransferProhibiter.cs b/src/LibHac/FsSrv/Sf/ISaveDataTransferProhibiter.cs new file mode 100644 index 00000000..62a904ad --- /dev/null +++ b/src/LibHac/FsSrv/Sf/ISaveDataTransferProhibiter.cs @@ -0,0 +1,9 @@ +using System; + +namespace LibHac.FsSrv.Sf +{ + public interface ISaveDataTransferProhibiter : IDisposable + { + // No methods. Disposing the service object removes the prohibition. + } +} \ No newline at end of file