Add more TSEC key generation

This commit is contained in:
Alex Barney 2023-01-29 22:26:34 -07:00
parent c6127972f8
commit bb13864030
6 changed files with 196 additions and 67 deletions

View file

@ -1,3 +1,7 @@
tsec_auth_signature_00 = A77B86586AE1B03D4FFBA3ADA8F8DE32
tsec_auth_signature_01 = A3FFB0F6BC49A06DF2FC791697D81D32
tsec_auth_signature_02 = 0B55CC0820E6307FD087479EAA2E7F98
keyblob_mac_key_source = 59C7FB6FBE9BBE87656B15C0537336A5
keyblob_key_source_00 = DF206F594454EFDC7074483B0DED9FD3
keyblob_key_source_01 = 0C25615D684CEB421C2379EA822512AC

View file

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using static LibHac.Common.Keys.KeySet;
using Type = LibHac.Common.Keys.KeyInfo.KeyType;
namespace LibHac.Common.Keys;
@ -103,40 +104,42 @@ internal static partial class DefaultKeySet
keys.Add(new KeyInfo(11, Type.DeviceRoot, "tsec_key", (set, _) => set.TsecKey));
keys.Add(new KeyInfo(12, Type.DeviceDrvd, "device_key", (set, _) => set.DeviceKey));
keys.Add(new KeyInfo(20, Type.CommonRoot, "tsec_root_kek", (set, _) => set.TsecRootKek));
keys.Add(new KeyInfo(21, Type.CommonRoot, "package1_mac_kek", (set, _) => set.Package1MacKek));
keys.Add(new KeyInfo(22, Type.CommonRoot, "package1_kek", (set, _) => set.Package1Kek));
keys.Add(new KeyInfo(15, Type.CommonRootSame, "tsec_secret", 0, TsecSecretCount, (set, i) => set.TsecSecrets[i]));
keys.Add(new KeyInfo(20, Type.CommonRoot, "tsec_root_kek", 0, TsecKeyRevisionCount, (set, i) => set.TsecRootKeks[i]));
keys.Add(new KeyInfo(22, Type.CommonRoot, "package1_mac_kek", 0, TsecKeyRevisionCount, (set, i) => set.Package1MacKeks[i]));
keys.Add(new KeyInfo(24, Type.CommonRoot, "package1_kek", 0, TsecKeyRevisionCount, (set, i) => set.Package1Keks[i]));
keys.Add(new KeyInfo(30, Type.CommonRoot, "tsec_auth_signature", 0, 0x20, (set, i) => set.TsecAuthSignatures[i]));
keys.Add(new KeyInfo(30, Type.CommonSeed, "tsec_auth_signature", 0, TsecKeyRevisionCount, (set, i) => set.TsecAuthSignatures[i]));
keys.Add(new KeyInfo(40, Type.CommonRoot, "tsec_root_key", 0, 0x20, (set, i) => set.TsecRootKeys[i]));
keys.Add(new KeyInfo(40, Type.CommonRoot, "tsec_root_key", 0, TsecKeyRevisionCount, (set, i) => set.TsecRootKeys[i]));
keys.Add(new KeyInfo(50, Type.CommonSeed, "keyblob_mac_key_source", (set, _) => set.KeyBlobMacKeySource));
keys.Add(new KeyInfo(51, Type.CommonSeed, "keyblob_key_source", 0, 6, (set, i) => set.KeyBlobKeySources[i]));
keys.Add(new KeyInfo(51, Type.CommonSeed, "keyblob_key_source", 0, UsedKeyBlobCount, (set, i) => set.KeyBlobKeySources[i]));
keys.Add(new KeyInfo(55, Type.DeviceDrvd, "keyblob_key", 0, 6, (set, i) => set.KeyBlobKeys[i]));
keys.Add(new KeyInfo(55, Type.DeviceDrvd, "keyblob_key", 0, UsedKeyBlobCount, (set, i) => set.KeyBlobKeys[i]));
keys.Add(new KeyInfo(60, Type.DeviceDrvd, "keyblob_mac_key", 0, 6, (set, i) => set.KeyBlobMacKeys[i]));
keys.Add(new KeyInfo(60, Type.DeviceDrvd, "keyblob_mac_key", 0, UsedKeyBlobCount, (set, i) => set.KeyBlobMacKeys[i]));
keys.Add(new KeyInfo(70, Type.DeviceRoot, "encrypted_keyblob", 0, 6, (set, i) => set.EncryptedKeyBlobs[i].Bytes));
keys.Add(new KeyInfo(70, Type.DeviceRoot, "encrypted_keyblob", 0, UsedKeyBlobCount, (set, i) => set.EncryptedKeyBlobs[i].Bytes));
keys.Add(new KeyInfo(80, Type.CommonRoot, "keyblob", 0, 6, (set, i) => set.KeyBlobs[i].Bytes));
keys.Add(new KeyInfo(80, Type.CommonRoot, "keyblob", 0, UsedKeyBlobCount, (set, i) => set.KeyBlobs[i].Bytes));
keys.Add(new KeyInfo(90, Type.CommonSeed, "master_kek_source", 6, 0x20, (set, i) => set.MasterKekSources[i]));
keys.Add(new KeyInfo(90, Type.CommonSeed, "master_kek_source", UsedKeyBlobCount, KeyRevisionCount, (set, i) => set.MasterKekSources[i]));
keys.Add(new KeyInfo(100, Type.CommonRoot, "mariko_bek", (set, _) => set.MarikoBek));
keys.Add(new KeyInfo(101, Type.CommonRoot, "mariko_kek", (set, _) => set.MarikoKek));
keys.Add(new KeyInfo(110, Type.CommonRoot, "mariko_aes_class_key", 0, 0xC, (set, i) => set.MarikoAesClassKeys[i]));
keys.Add(new KeyInfo(120, Type.CommonSeedDiff, "mariko_master_kek_source", 0, 0x20, (set, i) => set.MarikoMasterKekSources[i]));
keys.Add(new KeyInfo(130, Type.CommonDrvd, "master_kek", 0, 0x20, (set, i) => set.MasterKeks[i]));
keys.Add(new KeyInfo(110, Type.CommonRoot, "mariko_aes_class_key", 0, MarikoAesClassKeyCount, (set, i) => set.MarikoAesClassKeys[i]));
keys.Add(new KeyInfo(120, Type.CommonSeedDiff, "mariko_master_kek_source", 0, KeyRevisionCount, (set, i) => set.MarikoMasterKekSources[i]));
keys.Add(new KeyInfo(130, Type.CommonDrvd, "master_kek", 0, KeyRevisionCount, (set, i) => set.MasterKeks[i]));
keys.Add(new KeyInfo(140, Type.CommonSeed, "master_key_source", (set, _) => set.MasterKeySource));
keys.Add(new KeyInfo(150, Type.CommonDrvd, "master_key", 0, 0x20, (set, i) => set.MasterKeys[i]));
keys.Add(new KeyInfo(150, Type.CommonDrvd, "master_key", 0, KeyRevisionCount, (set, i) => set.MasterKeys[i]));
keys.Add(new KeyInfo(160, Type.CommonDrvd, "package1_key", 0, 0x20, (set, i) => set.Package1Keys[i]));
keys.Add(new KeyInfo(170, Type.CommonDrvd, "package1_mac_key", 6, 0x20, (set, i) => set.Package1MacKeys[i]));
keys.Add(new KeyInfo(160, Type.CommonDrvd, "package1_key", 0, KeyRevisionCount, (set, i) => set.Package1Keys[i]));
keys.Add(new KeyInfo(170, Type.CommonDrvd, "package1_mac_key", UsedKeyBlobCount, KeyRevisionCount, (set, i) => set.Package1MacKeys[i]));
keys.Add(new KeyInfo(180, Type.CommonSeed, "package2_key_source", (set, _) => set.Package2KeySource));
keys.Add(new KeyInfo(190, Type.CommonDrvd, "package2_key", 0, 0x20, (set, i) => set.Package2Keys[i]));
keys.Add(new KeyInfo(190, Type.CommonDrvd, "package2_key", 0, KeyRevisionCount, (set, i) => set.Package2Keys[i]));
keys.Add(new KeyInfo(200, Type.CommonSeed, "bis_kek_source", (set, _) => set.BisKekSource));
keys.Add(new KeyInfo(201, Type.CommonSeed, "bis_key_source", 0, 4, (set, i) => set.BisKeySources[i]));
@ -149,7 +152,7 @@ internal static partial class DefaultKeySet
keys.Add(new KeyInfo(213, Type.CommonSeed, "aes_key_generation_source", (set, _) => set.AesKeyGenerationSource));
keys.Add(new KeyInfo(214, Type.CommonSeed, "titlekek_source", (set, _) => set.TitleKekSource));
keys.Add(new KeyInfo(220, Type.CommonDrvd, "titlekek", 0, 0x20, (set, i) => set.TitleKeks[i]));
keys.Add(new KeyInfo(220, Type.CommonDrvd, "titlekek", 0, KeyRevisionCount, (set, i) => set.TitleKeks[i]));
keys.Add(new KeyInfo(230, Type.CommonSeed, "header_kek_source", (set, _) => set.HeaderKekSource));
keys.Add(new KeyInfo(231, Type.CommonSeed, "header_key_source", (set, _) => set.HeaderKeySource));
@ -175,15 +178,15 @@ internal static partial class DefaultKeySet
keys.Add(new KeyInfo(263, Type.CommonSeed, "sd_card_nca_key_source", (set, _) => set.SdCardKeySources[1]));
keys.Add(new KeyInfo(264, Type.CommonSeed, "sd_card_custom_storage_key_source", (set, _) => set.SdCardKeySources[2]));
keys.Add(new KeyInfo(270, Type.CommonSeedDiff, "xci_header_key", (set, _) => set.XciHeaderKey));
keys.Add(new KeyInfo(270, Type.CommonRoot, "xci_header_key", (set, _) => set.XciHeaderKey));
keys.Add(new KeyInfo(271, Type.CommonRoot, "xci_t1_titlekey_kek", 0, 0x10, (set, i) => set.GcTitleKeyKeks[i]));
keys.Add(new KeyInfo(280, Type.CommonRoot, "eticket_rsa_kek", (set, _) => set.ETicketRsaKek));
keys.Add(new KeyInfo(281, Type.CommonRoot, "ssl_rsa_kek", (set, _) => set.SslRsaKek));
keys.Add(new KeyInfo(290, Type.CommonDrvd, "key_area_key_application", 0, 0x20, (set, i) => set.KeyAreaKeys[i][0]));
keys.Add(new KeyInfo(300, Type.CommonDrvd, "key_area_key_ocean", 0, 0x20, (set, i) => set.KeyAreaKeys[i][1]));
keys.Add(new KeyInfo(310, Type.CommonDrvd, "key_area_key_system", 0, 0x20, (set, i) => set.KeyAreaKeys[i][2]));
keys.Add(new KeyInfo(290, Type.CommonDrvd, "key_area_key_application", 0, KeyRevisionCount, (set, i) => set.KeyAreaKeys[i][0]));
keys.Add(new KeyInfo(300, Type.CommonDrvd, "key_area_key_ocean", 0, KeyRevisionCount, (set, i) => set.KeyAreaKeys[i][1]));
keys.Add(new KeyInfo(310, Type.CommonDrvd, "key_area_key_system", 0, KeyRevisionCount, (set, i) => set.KeyAreaKeys[i][2]));
return keys;
}

View file

@ -12,26 +12,34 @@ namespace LibHac.Common.Keys;
public static class ExternalKeyWriter
{
public static void PrintKeys(KeySet keySet, StringBuilder sb, List<KeyInfo> keys, Type filter, bool isDev)
public static void PrintKeys(KeySet keySet, StringBuilder sb, List<KeyInfo> keys, Type filter, bool onlyPrintDifferentDevKeys)
{
if (keys.Count == 0) return;
string devSuffix = isDev ? "_dev" : string.Empty;
string devSuffix = onlyPrintDifferentDevKeys ? "_dev" : string.Empty;
int maxNameLength = keys.Max(x => x.NameLength);
int currentGroup = 0;
// Todo: Better filtering
bool FilterMatches(KeyInfo keyInfo)
{
Type filter1 = filter & (Type.Common | Type.Device);
Type filter2 = filter & (Type.Root | Type.Seed | Type.Derived);
Type filter3 = filter & Type.DifferentDev;
// If we're only printing dev-only keys, skip keys that are the same in both prod and dev environments.
if (onlyPrintDifferentDevKeys && !keyInfo.Type.HasFlag(Type.DifferentDev))
return false;
// Skip sub-filters that have no flags set
return (filter1 == 0 || (filter1 & keyInfo.Type) != 0) &&
(filter2 == 0 || (filter2 & keyInfo.Type) != 0) &&
filter3 == (filter3 & keyInfo.Type) ||
isDev && keyInfo.Type.HasFlag(Type.DifferentDev);
// A KeyType contains two sub-types that specify how a key is used in the cryptosystem, and whether a key
// is shared between all consoles or is console-unique. Each of these types are filtered separately.
// A key must match both of these sub-types to pass through the filter.
// A value of 0 for a sub-filter means that any value of the filtered sub-type is allowed.
const Type distributionTypeMask = Type.Common | Type.Device;
const Type derivationTypeMask = Type.Root | Type.Seed | Type.Derived;
Type distributionTypeFilter = filter & distributionTypeMask;
Type derivationTypeFilter = filter & derivationTypeMask;
bool matchesDistributionTypeFilter = distributionTypeFilter == 0 || (distributionTypeFilter & keyInfo.Type) != 0;
bool matchesDerivationTypeFilter = derivationTypeFilter == 0 || (derivationTypeFilter & keyInfo.Type) != 0;
return matchesDistributionTypeFilter && matchesDerivationTypeFilter;
}
bool isFirstPrint = true;
@ -118,8 +126,7 @@ public static class ExternalKeyWriter
public static string PrintCommonKeys(KeySet keySet)
{
var sb = new StringBuilder();
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common | Type.Root | Type.Seed | Type.Derived,
false);
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common, false);
return sb.ToString();
}
@ -146,7 +153,7 @@ public static class ExternalKeyWriter
{
sb.AppendLine();
keySet.SetMode(KeySet.Mode.Dev);
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common | Type.Seed | Type.DifferentDev, true);
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common | Type.Seed, true);
keySet.SetMode(KeySet.Mode.Prod);
}
@ -159,12 +166,11 @@ public static class ExternalKeyWriter
var sb = new StringBuilder();
keySet.SetMode(KeySet.Mode.Prod);
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common | Type.Root | Type.Seed | Type.Derived,
false);
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common, false);
sb.AppendLine();
keySet.SetMode(KeySet.Mode.Dev);
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common | Type.Root | Type.Derived, true);
PrintKeys(keySet, sb, DefaultKeySet.CreateKeyList(), Type.Common, true);
keySet.SetMode(originalMode);
return sb.ToString();

View file

@ -1,18 +1,21 @@
using System;
using System.Runtime.InteropServices;
using LibHac.Crypto;
using LibHac.Diag;
namespace LibHac.Common.Keys;
internal static class KeyDerivation
{
private const int HoviSeedSize = 0x10;
public static void DeriveAllKeys(KeySet keySet, IProgressReport logger = null)
{
DeriveKeyBlobKeys(keySet);
DecryptKeyBlobs(keySet, logger);
ReadKeyBlobs(keySet);
Derive620Keys(keySet);
DeriveTsecKeys(keySet);
Derive620MasterKeks(keySet);
DeriveMarikoMasterKeks(keySet);
DeriveMasterKeys(keySet);
@ -46,6 +49,9 @@ internal static class KeyDerivation
private static void DecryptKeyBlobs(KeySet s, IProgressReport logger = null)
{
if (s.CurrentMode == KeySet.Mode.Dev)
return;
var cmac = new AesCmac();
for (int i = 0; i < KeySet.UsedKeyBlobCount; i++)
@ -78,33 +84,115 @@ internal static class KeyDerivation
}
}
private static void Derive620Keys(KeySet s)
private enum HoviSeedType
{
bool haveTsecRootKek = !s.TsecRootKek.IsZeros();
bool havePackage1MacKek = !s.Package1MacKek.IsZeros();
bool havePackage1Kek = !s.Package1Kek.IsZeros();
Encryption,
Signature,
Kek,
// TSEC directly uses the value generated by this (no key derivation) to encrypt pk11's AES IV that's found
// at 0x6FF0 in package1. When decrypting pk11, TSEC will overwrite the unencrypted IV in package1 with the
// encrypted IV.
IvEncryption
}
for (int i = KeySet.UsedKeyBlobCount; i < KeySet.KeyRevisionCount; i++)
private static void DeriveTsecKeys(KeySet s)
{
AesKey secret26 = s.TsecSecrets[0x26];
bool haveSecret26 = !secret26.IsZeros();
bool isProd = s.CurrentMode == KeySet.Mode.Prod;
for (int i = 0; i < KeySet.TsecKeyRevisionCount; i++)
{
if (s.TsecAuthSignatures[i - KeySet.UsedKeyBlobCount].IsZeros())
continue;
if (s.TsecAuthSignatures[i].IsZeros()) continue;
if (haveTsecRootKek)
if (haveSecret26)
{
Aes.EncryptEcb128(s.TsecAuthSignatures[i - KeySet.UsedKeyBlobCount],
s.TsecRootKeys[i - KeySet.UsedKeyBlobCount], s.TsecRootKek);
DeriveTsecKeyFromSecret(i, HoviSeedType.Encryption, isProd, secret26, s.Package1Keks[i]);
DeriveTsecKeyFromSecret(i, HoviSeedType.Signature, isProd, secret26, s.Package1MacKeks[i]);
DeriveTsecKeyFromSecret(i, HoviSeedType.Kek, isProd, secret26, s.TsecRootKeks[i]);
}
if (havePackage1MacKek)
if (!s.Package1Keks[i].IsZeros())
{
Aes.EncryptEcb128(s.TsecAuthSignatures[i - KeySet.UsedKeyBlobCount], s.Package1MacKeys[i],
s.Package1MacKek);
Aes.EncryptEcb128(s.TsecAuthSignatures[i], s.Package1Keys[KeySet.UsedKeyBlobCount + i], s.Package1Keks[i]);
}
if (havePackage1Kek)
if (!s.Package1MacKeks[i].IsZeros())
{
Aes.EncryptEcb128(s.TsecAuthSignatures[i - KeySet.UsedKeyBlobCount], s.Package1Keys[i], s.Package1Kek);
Aes.EncryptEcb128(s.TsecAuthSignatures[i], s.Package1MacKeys[KeySet.UsedKeyBlobCount + i], s.Package1MacKeks[i]);
}
if (!s.TsecRootKeks[i].IsZeros())
{
Aes.EncryptEcb128(s.TsecAuthSignatures[i], s.TsecRootKeys[i], s.TsecRootKeks[i]);
}
}
static void DeriveTsecKeyFromSecret(int keyVersion, HoviSeedType type, bool isProd, ReadOnlySpan<byte> secret, Span<byte> output)
{
Span<byte> hoviSeed = stackalloc byte[HoviSeedSize];
GenerateHoviSeed(hoviSeed, type, isProd);
// The third version of the post-6.2.0 TSEC firmwares changed how these keys are derived. Instead of
// encrypting the seed, they now decrypt the seed.
if (keyVersion <= 1)
{
Aes.EncryptEcb128(hoviSeed, output, secret);
}
else
{
Aes.DecryptEcb128(hoviSeed, output, secret);
}
}
}
private static void GenerateHoviSeed(Span<byte> outSeed, HoviSeedType type, bool isProd)
{
const uint part1Hov = 0x49564F48; // HOVI
const uint part2Sig = 0x4749535F; // _SIG
const uint part2Kek = 0x4B454B5F; // _KEK
const uint part2Enc = 0x434E455F; // _ENC
const uint part3Key = 0x59454B5F; // _KEY
const uint part4Prd = 0x4452505F; // _PRD
const uint part4Dev = 0x5645445F; // _DEV
const uint part4Iv1 = 0x3156495F; // _IV1
Assert.GreaterEqual(outSeed.Length, HoviSeedSize);
Span<uint> seed = MemoryMarshal.Cast<byte, uint>(outSeed);
seed[0] = part1Hov;
switch (type)
{
case HoviSeedType.Encryption:
seed[1] = part2Enc;
break;
case HoviSeedType.Signature:
seed[1] = part2Sig;
break;
case HoviSeedType.Kek:
seed[1] = part2Kek;
break;
case HoviSeedType.IvEncryption:
seed[1] = part2Enc;
break;
}
seed[2] = part3Key;
if (type == HoviSeedType.IvEncryption)
{
seed[3] = part4Iv1;
}
else if (isProd)
{
seed[3] = part4Prd;
}
else
{
seed[3] = part4Dev;
}
}

View file

@ -17,8 +17,17 @@ public readonly struct KeyInfo
[Flags]
public enum KeyType : byte
{
// These two flags specify whether a key is common to all consoles or is console-unique.
// Only one of these flags should be set at a time.
Common = 1 << 0,
Device = 1 << 1,
// These three flags specify how a key is obtained. Only one of these flags should be set at a time.
// Root keys are generally used to transform the key seeds into actual keys.
// These root keys are usually not supposed to be exposed outside of TrustZone or the TSEC firmware.
// Other root keys might be stored directly in system software and used without transforming the key first.
// Seeds are generally stored as plaintext in system software and are used as seeds to generate the actual keys.
// Derived keys are the keys that are generated from the key seeds.
Root = 1 << 2,
Seed = 1 << 3,
Derived = 1 << 4,
@ -26,10 +35,11 @@ public readonly struct KeyInfo
/// <summary>Specifies that a seed is different in prod and dev.</summary>
DifferentDev = 1 << 5,
CommonRoot = Common | Root,
CommonRoot = Common | Root | DifferentDev,
CommonRootSame = Common | Root,
CommonSeed = Common | Seed,
CommonSeedDiff = Common | Seed | DifferentDev,
CommonDrvd = Common | Derived,
CommonDrvd = Common | Derived | DifferentDev,
DeviceRoot = Device | Root,
DeviceDrvd = Device | Derived
}

View file

@ -23,6 +23,15 @@ public class KeySet
internal const int UsedKeyBlobCount = 6;
internal const int SdCardKeyIdCount = 3;
internal const int KeyRevisionCount = 0x20;
internal const int TsecSecretCount = 0x40;
internal const int MarikoAesClassKeyCount = 0xC;
/// <summary>
/// The number of slots reserved for current and future TSEC FW revisions.
/// 8 was semi-arbitrarily chosen because there are only 3 FW revisions used for &gt;= 6.2.0 crypto as of Jan 2023,
/// and it's unlikely that many more will be issued.
/// </summary>
internal const int TsecKeyRevisionCount = 8;
private AllKeys _keys;
private Mode _mode = Mode.Prod;
@ -30,6 +39,7 @@ public class KeySet
public ref AllKeys KeyStruct => ref _keys;
public Mode CurrentMode => _mode;
private ref TsecSecrets Secrets => ref _keys.TsecSecrets;
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;
@ -49,10 +59,12 @@ public class KeySet
public Span<KeyBlob> KeyBlobs => RootKeys.KeyBlobs.Items;
public Span<AesKey> KeyBlobKeySources => _keys.KeySeeds.KeyBlobKeySources.Items;
public ref AesKey KeyBlobMacKeySource => ref _keys.KeySeeds.KeyBlobMacKeySource;
public ref AesKey TsecRootKek => ref RootKeys.TsecRootKek;
public ref AesKey Package1MacKek => ref RootKeys.Package1MacKek;
public ref AesKey Package1Kek => ref RootKeys.Package1Kek;
public Span<AesKey> TsecAuthSignatures => RootKeys.TsecAuthSignatures.Items;
public Span<AesKey> TsecSecrets => Secrets.Secrets.Items;
public Span<AesKey> TsecRootKeks => RootKeys.TsecRootKeks.Items;
public Span<AesKey> Package1MacKeks => RootKeys.Package1MacKeks.Items;
public Span<AesKey> Package1Keks => RootKeys.Package1Keks.Items;
public Span<AesKey> TsecAuthSignatures => _keys.KeySeeds.TsecAuthSignatures.Items;
public Span<AesKey> TsecRootKeys => RootKeys.TsecRootKeys.Items;
public Span<AesKey> MasterKekSources => _keys.KeySeeds.MasterKekSources.Items;
public Span<AesKey> GcTitleKeyKeks => RootKeys.GcTitleKeyKeks.Items;
@ -263,6 +275,7 @@ public class KeySet
public struct AllKeys
{
public TsecSecrets TsecSecrets;
public RootKeys RootKeysDev;
public RootKeys RootKeysProd;
public KeySeeds KeySeeds;
@ -278,6 +291,11 @@ public struct AllKeys
public RsaKeys RsaKeys;
}
public struct TsecSecrets
{
public Array64<AesKey> Secrets;
}
public struct RootKeys
{
// Mariko keys. The AES class keys are currently unused.
@ -291,13 +309,12 @@ public struct RootKeys
public Array32<KeyBlob> KeyBlobs;
// Used by TSEC in >= 6.2.0 Erista firmware
public Array32<AesKey> TsecAuthSignatures;
public AesKey TsecRootKek;
public AesKey Package1MacKek;
public AesKey Package1Kek;
public Array8<AesKey> TsecRootKeks;
public Array8<AesKey> Package1MacKeks;
public Array8<AesKey> Package1Keks;
// Derived by TSEC. This is the first public root key for >= 6.2.0 Erista
public Array32<AesKey> TsecRootKeys;
public Array8<AesKey> TsecRootKeys;
// Used to decrypt the title keys found in an XCI's initial data
public Array16<AesKey> GcTitleKeyKeks;
@ -305,6 +322,7 @@ public struct RootKeys
public struct KeySeeds
{
public Array8<AesKey> TsecAuthSignatures;
public Array32<AesKey> KeyBlobKeySources;
public AesKey KeyBlobMacKeySource;
public Array32<AesKey> MasterKekSources;