From fe8699e8c446380dbcc533edaab6f93a06b4b0b1 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 22 Nov 2022 23:45:14 -0700 Subject: [PATCH] Split out derived device keys into separate prod/dev groups This fixes an issue where reading certain device keys/seeds would result in dev derived keys instead of prod derived keys --- build/CodeGen/Stage2/KeysCodeGen.cs | 6 ++-- src/LibHac/Common/Keys/DefaultKeySet.Empty.cs | 2 ++ src/LibHac/Common/Keys/DefaultKeySet.cs | 34 ++++++++++++------- src/LibHac/Common/Keys/KeySet.cs | 28 +++++++++------ 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/build/CodeGen/Stage2/KeysCodeGen.cs b/build/CodeGen/Stage2/KeysCodeGen.cs index 3b483bf3..ecb8abdf 100644 --- a/build/CodeGen/Stage2/KeysCodeGen.cs +++ b/build/CodeGen/Stage2/KeysCodeGen.cs @@ -11,8 +11,8 @@ namespace LibHacBuild.CodeGen.Stage2; public static class KeysCodeGen { - private static string InputMainKeyFileName = "IncludedKeys.txt"; - private static string GeneratedFilePath = "LibHac/Common/Keys/DefaultKeySet.Generated.cs"; + private const string InputMainKeyFileName = "IncludedKeys.txt"; + private const string GeneratedFilePath = "LibHac/Common/Keys/DefaultKeySet.Generated.cs"; public static void Run() { @@ -45,6 +45,8 @@ public static class KeysCodeGen BuildArray(sb, "DerivedKeysDev", SpanHelpers.AsReadOnlyByteSpan(in keySet.KeyStruct.DerivedKeysDev)); BuildArray(sb, "DerivedKeysProd", SpanHelpers.AsReadOnlyByteSpan(in keySet.KeyStruct.DerivedKeysProd)); BuildArray(sb, "DeviceKeys", SpanHelpers.AsReadOnlyByteSpan(in keySet.KeyStruct.DeviceKeys)); + BuildArray(sb, "DerivedDeviceKeysDev", SpanHelpers.AsReadOnlyByteSpan(in keySet.KeyStruct.DerivedDeviceKeysDev)); + BuildArray(sb, "DerivedDeviceKeysProd", SpanHelpers.AsReadOnlyByteSpan(in keySet.KeyStruct.DerivedDeviceKeysProd)); BuildArray(sb, "RsaSigningKeysDev", SpanHelpers.AsReadOnlyByteSpan(in keySet.KeyStruct.RsaSigningKeysDev)); BuildArray(sb, "RsaSigningKeysProd", SpanHelpers.AsReadOnlyByteSpan(in keySet.KeyStruct.RsaSigningKeysProd)); BuildArray(sb, "RsaKeys", SpanHelpers.AsReadOnlyByteSpan(in keySet.KeyStruct.RsaKeys)); diff --git a/src/LibHac/Common/Keys/DefaultKeySet.Empty.cs b/src/LibHac/Common/Keys/DefaultKeySet.Empty.cs index cbba6f1a..944293b1 100644 --- a/src/LibHac/Common/Keys/DefaultKeySet.Empty.cs +++ b/src/LibHac/Common/Keys/DefaultKeySet.Empty.cs @@ -12,6 +12,8 @@ internal static partial class DefaultKeySet private static ReadOnlySpan DerivedKeysDev => new byte[] { }; private static ReadOnlySpan DerivedKeysProd => new byte[] { }; private static ReadOnlySpan DeviceKeys => new byte[] { }; + private static ReadOnlySpan DerivedDeviceKeysDev => new byte[] { }; + private static ReadOnlySpan DerivedDeviceKeysProd => new byte[] { }; private static ReadOnlySpan RsaSigningKeysDev => new byte[] { }; private static ReadOnlySpan RsaSigningKeysProd => new byte[] { }; private static ReadOnlySpan RsaKeys => new byte[] { }; diff --git a/src/LibHac/Common/Keys/DefaultKeySet.cs b/src/LibHac/Common/Keys/DefaultKeySet.cs index bdc2dce6..58366e6a 100644 --- a/src/LibHac/Common/Keys/DefaultKeySet.cs +++ b/src/LibHac/Common/Keys/DefaultKeySet.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using Type = LibHac.Common.Keys.KeyInfo.KeyType; namespace LibHac.Common.Keys; @@ -16,59 +15,70 @@ internal static partial class DefaultKeySet var keySet = new KeySet(); // Fill the key set with any key structs included in the library. + // This is split into multiple parts so the binary size isn't increased when providing only some keys. if (RootKeysDev.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.RootKeysDev = MemoryMarshal.Cast(RootKeysDev)[0]; + keySet.KeyStruct.RootKeysDev = SpanHelpers.AsReadOnlyStruct(RootKeysDev); } if (RootKeysProd.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.RootKeysProd = MemoryMarshal.Cast(RootKeysProd)[0]; + keySet.KeyStruct.RootKeysProd = SpanHelpers.AsReadOnlyStruct(RootKeysProd); } if (KeySeeds.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.KeySeeds = MemoryMarshal.Cast(KeySeeds)[0]; + keySet.KeyStruct.KeySeeds = SpanHelpers.AsReadOnlyStruct(KeySeeds); } if (StoredKeysDev.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.StoredKeysDev = MemoryMarshal.Cast(StoredKeysDev)[0]; + keySet.KeyStruct.StoredKeysDev = SpanHelpers.AsReadOnlyStruct(StoredKeysDev); } if (StoredKeysProd.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.StoredKeysProd = MemoryMarshal.Cast(StoredKeysProd)[0]; + keySet.KeyStruct.StoredKeysProd = SpanHelpers.AsReadOnlyStruct(StoredKeysProd); } if (DerivedKeysDev.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.DerivedKeysDev = MemoryMarshal.Cast(DerivedKeysDev)[0]; + keySet.KeyStruct.DerivedKeysDev = SpanHelpers.AsReadOnlyStruct(DerivedKeysDev); } if (DerivedKeysProd.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.DerivedKeysProd = MemoryMarshal.Cast(DerivedKeysProd)[0]; + keySet.KeyStruct.DerivedKeysProd = SpanHelpers.AsReadOnlyStruct(DerivedKeysProd); } if (DeviceKeys.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.DeviceKeys = MemoryMarshal.Cast(DeviceKeys)[0]; + keySet.KeyStruct.DeviceKeys = SpanHelpers.AsReadOnlyStruct(DeviceKeys); + } + + if (DerivedDeviceKeysDev.Length == Unsafe.SizeOf()) + { + keySet.KeyStruct.DerivedDeviceKeysDev = SpanHelpers.AsReadOnlyStruct(DerivedDeviceKeysDev); + } + + if (DerivedDeviceKeysProd.Length == Unsafe.SizeOf()) + { + keySet.KeyStruct.DerivedDeviceKeysProd = SpanHelpers.AsReadOnlyStruct(DerivedDeviceKeysProd); } if (RsaSigningKeysDev.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.RsaSigningKeysDev = MemoryMarshal.Cast(RsaSigningKeysDev)[0]; + keySet.KeyStruct.RsaSigningKeysDev = SpanHelpers.AsReadOnlyStruct(RsaSigningKeysDev); } if (RsaSigningKeysProd.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.RsaSigningKeysProd = MemoryMarshal.Cast(RsaSigningKeysProd)[0]; + keySet.KeyStruct.RsaSigningKeysProd = SpanHelpers.AsReadOnlyStruct(RsaSigningKeysProd); } if (RsaKeys.Length == Unsafe.SizeOf()) { - keySet.KeyStruct.RsaKeys = MemoryMarshal.Cast(RsaKeys)[0]; + keySet.KeyStruct.RsaKeys = SpanHelpers.AsReadOnlyStruct(RsaKeys); } return keySet; diff --git a/src/LibHac/Common/Keys/KeySet.cs b/src/LibHac/Common/Keys/KeySet.cs index a70dee9d..240d07f1 100644 --- a/src/LibHac/Common/Keys/KeySet.cs +++ b/src/LibHac/Common/Keys/KeySet.cs @@ -33,6 +33,7 @@ public class KeySet private ref RootKeys RootKeys => ref _mode == Mode.Dev ? ref _keys.RootKeysDev : ref _keys.RootKeysProd; private ref StoredKeys StoredKeys => ref _mode == Mode.Dev ? ref _keys.StoredKeysDev : ref _keys.StoredKeysProd; private ref DerivedKeys DerivedKeys => ref _mode == Mode.Dev ? ref _keys.DerivedKeysDev : ref _keys.DerivedKeysProd; + private ref DerivedDeviceKeys DerivedDeviceKeys => ref _mode == Mode.Dev ? ref _keys.DerivedDeviceKeysDev : ref _keys.DerivedDeviceKeysProd; private ref RsaSigningKeys RsaSigningKeys => ref _mode == Mode.Dev ? ref _keys.RsaSigningKeysDev : ref _keys.RsaSigningKeysProd; private ref RsaKeys RsaKeys => ref _keys.RsaKeys; @@ -94,17 +95,18 @@ public class KeySet public ref AesKey SecureBootKey => ref _keys.DeviceKeys.SecureBootKey; public ref AesKey TsecKey => ref _keys.DeviceKeys.TsecKey; - public Span KeyBlobKeys => _keys.DeviceKeys.KeyBlobKeys.Items; - public Span KeyBlobMacKeys => _keys.DeviceKeys.KeyBlobMacKeys.Items; - public Span EncryptedKeyBlobs => _keys.DeviceKeys.EncryptedKeyBlobs.Items; - public ref AesKey DeviceKey => ref _keys.DeviceKeys.DeviceKey; - public Span BisKeys => _keys.DeviceKeys.BisKeys.Items; - public Span DeviceUniqueSaveMacKeys => _keys.DeviceKeys.DeviceUniqueSaveMacKeys.Items; - public ref AesKey SeedUniqueSaveMacKey => ref _keys.DeviceKeys.SeedUniqueSaveMacKey; public ref AesKey SdCardEncryptionSeed => ref _keys.DeviceKeys.SdCardEncryptionSeed; + public Span EncryptedKeyBlobs => _keys.DeviceKeys.EncryptedKeyBlobs.Items; + + public Span KeyBlobKeys => DerivedDeviceKeys.KeyBlobKeys.Items; + public Span KeyBlobMacKeys => DerivedDeviceKeys.KeyBlobMacKeys.Items; + public ref AesKey DeviceKey => ref DerivedDeviceKeys.DeviceKey; + public Span BisKeys => DerivedDeviceKeys.BisKeys.Items; + public Span DeviceUniqueSaveMacKeys => DerivedDeviceKeys.DeviceUniqueSaveMacKeys.Items; + public ref AesKey SeedUniqueSaveMacKey => ref DerivedDeviceKeys.SeedUniqueSaveMacKey; // Todo: Make a separate type? Not actually an AES-XTS key, but it's still the same shape. - public Span SdCardEncryptionKeys => _keys.DeviceKeys.SdCardEncryptionKeys.Items; + public Span SdCardEncryptionKeys => DerivedDeviceKeys.SdCardEncryptionKeys.Items; public Span NcaHeaderSigningKeys => RsaSigningKeys.NcaHeaderSigningKeys.Items; public Span AcidSigningKeys => RsaSigningKeys.AcidSigningKeys.Items; @@ -269,6 +271,8 @@ public struct AllKeys public DerivedKeys DerivedKeysDev; public DerivedKeys DerivedKeysProd; public DeviceKeys DeviceKeys; + public DerivedDeviceKeys DerivedDeviceKeysDev; + public DerivedDeviceKeys DerivedDeviceKeysProd; public RsaSigningKeys RsaSigningKeysDev; public RsaSigningKeys RsaSigningKeysProd; public RsaKeys RsaKeys; @@ -354,14 +358,18 @@ public struct DeviceKeys { public AesKey SecureBootKey; public AesKey TsecKey; + public AesKey SdCardEncryptionSeed; + public Array32 EncryptedKeyBlobs; +} + +public struct DerivedDeviceKeys +{ public Array32 KeyBlobKeys; public Array32 KeyBlobMacKeys; - public Array32 EncryptedKeyBlobs; public AesKey DeviceKey; public Array4 BisKeys; public Array2 DeviceUniqueSaveMacKeys; public AesKey SeedUniqueSaveMacKey; - public AesKey SdCardEncryptionSeed; public Array3 SdCardEncryptionKeys; }