mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Support 6.2.0 keygen
This commit is contained in:
parent
41b9f3088e
commit
b2e8ee53c0
3 changed files with 58 additions and 26 deletions
|
@ -10,12 +10,20 @@ namespace LibHac
|
||||||
{
|
{
|
||||||
public class Keyset
|
public class Keyset
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The number of keyblobs that were used for < 6.2.0 crypto
|
||||||
|
/// </summary>
|
||||||
|
private const int UsedKeyblobCount = 6;
|
||||||
|
|
||||||
public byte[][] KeyblobKeys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
public byte[][] KeyblobKeys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
public byte[][] KeyblobMacKeys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
public byte[][] KeyblobMacKeys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
public byte[][] EncryptedKeyblobs { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0xB0);
|
public byte[][] EncryptedKeyblobs { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0xB0);
|
||||||
public byte[][] Keyblobs { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x90);
|
public byte[][] Keyblobs { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x90);
|
||||||
public byte[][] KeyblobKeySources { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
public byte[][] KeyblobKeySources { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
public byte[] KeyblobMacKeySource { get; } = new byte[0x10];
|
public byte[] KeyblobMacKeySource { get; } = new byte[0x10];
|
||||||
|
public byte[][] TsecRootKeys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
|
public byte[][] MasterKekSources { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
|
public byte[][] MasterKeks { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
public byte[] MasterKeySource { get; } = new byte[0x10];
|
public byte[] MasterKeySource { get; } = new byte[0x10];
|
||||||
public byte[][] MasterKeys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
public byte[][] MasterKeys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
public byte[][] Package1Keys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
public byte[][] Package1Keys { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
|
@ -28,29 +36,31 @@ namespace LibHac
|
||||||
public byte[] KeyAreaKeySystemSource { get; } = new byte[0x10];
|
public byte[] KeyAreaKeySystemSource { get; } = new byte[0x10];
|
||||||
public byte[] SaveMacKekSource { get; } = new byte[0x10];
|
public byte[] SaveMacKekSource { get; } = new byte[0x10];
|
||||||
public byte[] SaveMacKeySource { get; } = new byte[0x10];
|
public byte[] SaveMacKeySource { get; } = new byte[0x10];
|
||||||
public byte[] TitlekekSource { get; } = new byte[0x10];
|
public byte[] TitleKekSource { get; } = new byte[0x10];
|
||||||
public byte[] HeaderKekSource { get; } = new byte[0x10];
|
public byte[] HeaderKekSource { get; } = new byte[0x10];
|
||||||
public byte[] SdCardKekSource { get; } = new byte[0x10];
|
public byte[] SdCardKekSource { get; } = new byte[0x10];
|
||||||
public byte[][] SdCardKeySources { get; } = Util.CreateJaggedArray<byte[][]>(2, 0x20);
|
public byte[][] SdCardKeySources { get; } = Util.CreateJaggedArray<byte[][]>(2, 0x20);
|
||||||
public byte[][] SdCardKeySourcesSpecific { get; } = Util.CreateJaggedArray<byte[][]>(2, 0x20);
|
|
||||||
public byte[] HeaderKeySource { get; } = new byte[0x20];
|
public byte[] HeaderKeySource { get; } = new byte[0x20];
|
||||||
public byte[] HeaderKey { get; } = new byte[0x20];
|
public byte[] HeaderKey { get; } = new byte[0x20];
|
||||||
public byte[] XciHeaderKey { get; } = new byte[0x10];
|
public byte[] XciHeaderKey { get; } = new byte[0x10];
|
||||||
public byte[][] Titlekeks { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
public byte[][] TitleKeks { get; } = Util.CreateJaggedArray<byte[][]>(0x20, 0x10);
|
||||||
public byte[][][] KeyAreaKeys { get; } = Util.CreateJaggedArray<byte[][][]>(0x20, 3, 0x10);
|
public byte[][][] KeyAreaKeys { get; } = Util.CreateJaggedArray<byte[][][]>(0x20, 3, 0x10);
|
||||||
public byte[] SaveMacKey { get; } = new byte[0x10];
|
|
||||||
public byte[][] SdCardKeys { get; } = Util.CreateJaggedArray<byte[][]>(2, 0x20);
|
|
||||||
public byte[] EticketRsaKek { get; } = new byte[0x10];
|
public byte[] EticketRsaKek { get; } = new byte[0x10];
|
||||||
public byte[] RetailSpecificAesKeySource { get; } = new byte[0x10];
|
public byte[] RetailSpecificAesKeySource { get; } = new byte[0x10];
|
||||||
public byte[] PerConsoleKeySource { get; } = new byte[0x10];
|
public byte[] PerConsoleKeySource { get; } = new byte[0x10];
|
||||||
public byte[] BisKekSource { get; } = new byte[0x10];
|
public byte[] BisKekSource { get; } = new byte[0x10];
|
||||||
public byte[][] BisKeySource { get; } = Util.CreateJaggedArray<byte[][]>(3, 0x20);
|
public byte[][] BisKeySource { get; } = Util.CreateJaggedArray<byte[][]>(4, 0x20);
|
||||||
|
public byte[] SslRsaKek { get; } = new byte[0x10];
|
||||||
|
|
||||||
|
// Device-specific keys
|
||||||
public byte[] SecureBootKey { get; } = new byte[0x10];
|
public byte[] SecureBootKey { get; } = new byte[0x10];
|
||||||
public byte[] TsecKey { get; } = new byte[0x10];
|
public byte[] TsecKey { get; } = new byte[0x10];
|
||||||
public byte[] DeviceKey { get; } = new byte[0x10];
|
public byte[] DeviceKey { get; } = new byte[0x10];
|
||||||
public byte[][] BisKeys { get; } = Util.CreateJaggedArray<byte[][]>(4, 0x20);
|
public byte[][] BisKeys { get; } = Util.CreateJaggedArray<byte[][]>(4, 0x20);
|
||||||
|
public byte[] SaveMacKey { get; } = new byte[0x10];
|
||||||
public byte[] SdSeed { get; } = new byte[0x10];
|
public byte[] SdSeed { get; } = new byte[0x10];
|
||||||
|
public byte[][] SdCardKeySourcesSpecific { get; } = Util.CreateJaggedArray<byte[][]>(2, 0x20);
|
||||||
|
public byte[][] SdCardKeys { get; } = Util.CreateJaggedArray<byte[][]>(2, 0x20);
|
||||||
|
|
||||||
public RSAParameters EticketExtKeyRsa { get; set; }
|
public RSAParameters EticketExtKeyRsa { get; set; }
|
||||||
|
|
||||||
|
@ -128,6 +138,9 @@ namespace LibHac
|
||||||
DecryptKeyblobs(logger);
|
DecryptKeyblobs(logger);
|
||||||
ReadKeyblobs();
|
ReadKeyblobs();
|
||||||
|
|
||||||
|
Derive620MasterKeks();
|
||||||
|
DeriveMasterKeys();
|
||||||
|
|
||||||
DerivePerConsoleKeys();
|
DerivePerConsoleKeys();
|
||||||
DerivePerFirmwareKeys();
|
DerivePerFirmwareKeys();
|
||||||
DeriveNcaHeaderKey();
|
DeriveNcaHeaderKey();
|
||||||
|
@ -141,7 +154,7 @@ namespace LibHac
|
||||||
bool haveKeyblobMacKeySource = !MasterKeySource.IsEmpty();
|
bool haveKeyblobMacKeySource = !MasterKeySource.IsEmpty();
|
||||||
var temp = new byte[0x10];
|
var temp = new byte[0x10];
|
||||||
|
|
||||||
for (int i = 0; i < 0x20; i++)
|
for (int i = 0; i < UsedKeyblobCount; i++)
|
||||||
{
|
{
|
||||||
if (KeyblobKeySources[i].IsEmpty()) continue;
|
if (KeyblobKeySources[i].IsEmpty()) continue;
|
||||||
|
|
||||||
|
@ -160,7 +173,7 @@ namespace LibHac
|
||||||
var expectedCmac = new byte[0x10];
|
var expectedCmac = new byte[0x10];
|
||||||
var counter = new byte[0x10];
|
var counter = new byte[0x10];
|
||||||
|
|
||||||
for (int i = 0; i < 0x20; i++)
|
for (int i = 0; i < UsedKeyblobCount; i++)
|
||||||
{
|
{
|
||||||
if (KeyblobKeys[i].IsEmpty() || KeyblobMacKeys[i].IsEmpty() || EncryptedKeyblobs[i].IsEmpty())
|
if (KeyblobKeys[i].IsEmpty() || KeyblobMacKeys[i].IsEmpty() || EncryptedKeyblobs[i].IsEmpty())
|
||||||
{
|
{
|
||||||
|
@ -187,21 +200,34 @@ namespace LibHac
|
||||||
|
|
||||||
private void ReadKeyblobs()
|
private void ReadKeyblobs()
|
||||||
{
|
{
|
||||||
var masterKek = new byte[0x10];
|
for (int i = 0; i < UsedKeyblobCount; i++)
|
||||||
|
|
||||||
bool haveMasterKeySource = !MasterKeySource.IsEmpty();
|
|
||||||
|
|
||||||
for (int i = 0; i < 0x20; i++)
|
|
||||||
{
|
{
|
||||||
if (Keyblobs[i].IsEmpty()) continue;
|
if (Keyblobs[i].IsEmpty()) continue;
|
||||||
|
|
||||||
Array.Copy(Keyblobs[i], 0x80, Package1Keys[i], 0, 0x10);
|
Array.Copy(Keyblobs[i], 0x80, Package1Keys[i], 0, 0x10);
|
||||||
|
Array.Copy(Keyblobs[i], MasterKeks[i], 0x10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!haveMasterKeySource) continue;
|
private void Derive620MasterKeks()
|
||||||
|
{
|
||||||
|
for (int i = UsedKeyblobCount; i < 0x20; i++)
|
||||||
|
{
|
||||||
|
if (TsecRootKeys[i].IsEmpty() || MasterKekSources[i].IsEmpty()) continue;
|
||||||
|
|
||||||
Array.Copy(Keyblobs[i], masterKek, 0x10);
|
Crypto.DecryptEcb(TsecRootKeys[i], MasterKekSources[i], MasterKeks[i], 0x10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Crypto.DecryptEcb(masterKek, MasterKeySource, MasterKeys[i], 0x10);
|
private void DeriveMasterKeys()
|
||||||
|
{
|
||||||
|
if (MasterKeySource.IsEmpty()) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < 0x20; i++)
|
||||||
|
{
|
||||||
|
if (MasterKeks[i].IsEmpty()) continue;
|
||||||
|
|
||||||
|
Crypto.DecryptEcb(MasterKeks[i], MasterKeySource, MasterKeys[i], 0x10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +278,7 @@ namespace LibHac
|
||||||
bool haveKakSource0 = !KeyAreaKeyApplicationSource.IsEmpty();
|
bool haveKakSource0 = !KeyAreaKeyApplicationSource.IsEmpty();
|
||||||
bool haveKakSource1 = !KeyAreaKeyOceanSource.IsEmpty();
|
bool haveKakSource1 = !KeyAreaKeyOceanSource.IsEmpty();
|
||||||
bool haveKakSource2 = !KeyAreaKeySystemSource.IsEmpty();
|
bool haveKakSource2 = !KeyAreaKeySystemSource.IsEmpty();
|
||||||
bool haveTitleKekSource = !TitlekekSource.IsEmpty();
|
bool haveTitleKekSource = !TitleKekSource.IsEmpty();
|
||||||
bool havePackage2KeySource = !Package2KeySource.IsEmpty();
|
bool havePackage2KeySource = !Package2KeySource.IsEmpty();
|
||||||
|
|
||||||
for (int i = 0; i < 0x20; i++)
|
for (int i = 0; i < 0x20; i++)
|
||||||
|
@ -282,7 +308,7 @@ namespace LibHac
|
||||||
|
|
||||||
if (haveTitleKekSource)
|
if (haveTitleKekSource)
|
||||||
{
|
{
|
||||||
Crypto.DecryptEcb(MasterKeys[i], TitlekekSource, Titlekeks[i], 0x10);
|
Crypto.DecryptEcb(MasterKeys[i], TitleKekSource, TitleKeks[i], 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (havePackage2KeySource)
|
if (havePackage2KeySource)
|
||||||
|
@ -514,7 +540,7 @@ namespace LibHac
|
||||||
new KeyValue("key_area_key_application_source", 0x10, set => set.KeyAreaKeyApplicationSource),
|
new KeyValue("key_area_key_application_source", 0x10, set => set.KeyAreaKeyApplicationSource),
|
||||||
new KeyValue("key_area_key_ocean_source", 0x10, set => set.KeyAreaKeyOceanSource),
|
new KeyValue("key_area_key_ocean_source", 0x10, set => set.KeyAreaKeyOceanSource),
|
||||||
new KeyValue("key_area_key_system_source", 0x10, set => set.KeyAreaKeySystemSource),
|
new KeyValue("key_area_key_system_source", 0x10, set => set.KeyAreaKeySystemSource),
|
||||||
new KeyValue("titlekek_source", 0x10, set => set.TitlekekSource),
|
new KeyValue("titlekek_source", 0x10, set => set.TitleKekSource),
|
||||||
new KeyValue("header_kek_source", 0x10, set => set.HeaderKekSource),
|
new KeyValue("header_kek_source", 0x10, set => set.HeaderKekSource),
|
||||||
new KeyValue("header_key_source", 0x20, set => set.HeaderKeySource),
|
new KeyValue("header_key_source", 0x20, set => set.HeaderKeySource),
|
||||||
new KeyValue("header_key", 0x20, set => set.HeaderKey),
|
new KeyValue("header_key", 0x20, set => set.HeaderKey),
|
||||||
|
@ -531,7 +557,7 @@ namespace LibHac
|
||||||
new KeyValue("bis_kek_source", 0x10, set => set.BisKekSource),
|
new KeyValue("bis_kek_source", 0x10, set => set.BisKekSource),
|
||||||
new KeyValue("save_mac_kek_source", 0x10, set => set.SaveMacKekSource),
|
new KeyValue("save_mac_kek_source", 0x10, set => set.SaveMacKekSource),
|
||||||
new KeyValue("save_mac_key_source", 0x10, set => set.SaveMacKeySource),
|
new KeyValue("save_mac_key_source", 0x10, set => set.SaveMacKeySource),
|
||||||
new KeyValue("save_mac_key", 0x10, set => set.SaveMacKey)
|
new KeyValue("ssl_rsa_kek", 0x10, set => set.SslRsaKek)
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int slot = 0; slot < 0x20; slot++)
|
for (int slot = 0; slot < 0x20; slot++)
|
||||||
|
@ -539,16 +565,19 @@ namespace LibHac
|
||||||
int i = slot;
|
int i = slot;
|
||||||
keys.Add(new KeyValue($"keyblob_key_source_{i:x2}", 0x10, set => set.KeyblobKeySources[i]));
|
keys.Add(new KeyValue($"keyblob_key_source_{i:x2}", 0x10, set => set.KeyblobKeySources[i]));
|
||||||
keys.Add(new KeyValue($"keyblob_{i:x2}", 0x90, set => set.Keyblobs[i]));
|
keys.Add(new KeyValue($"keyblob_{i:x2}", 0x90, set => set.Keyblobs[i]));
|
||||||
|
keys.Add(new KeyValue($"tsec_root_key_{i:x2}", 0x10, set => set.TsecRootKeys[i]));
|
||||||
keys.Add(new KeyValue($"master_key_{i:x2}", 0x10, set => set.MasterKeys[i]));
|
keys.Add(new KeyValue($"master_key_{i:x2}", 0x10, set => set.MasterKeys[i]));
|
||||||
|
keys.Add(new KeyValue($"master_kek_{i:x2}", 0x10, set => set.MasterKeks[i]));
|
||||||
|
keys.Add(new KeyValue($"master_kek_source_{i:x2}", 0x10, set => set.MasterKekSources[i]));
|
||||||
keys.Add(new KeyValue($"package1_key_{i:x2}", 0x10, set => set.Package1Keys[i]));
|
keys.Add(new KeyValue($"package1_key_{i:x2}", 0x10, set => set.Package1Keys[i]));
|
||||||
keys.Add(new KeyValue($"package2_key_{i:x2}", 0x10, set => set.Package2Keys[i]));
|
keys.Add(new KeyValue($"package2_key_{i:x2}", 0x10, set => set.Package2Keys[i]));
|
||||||
keys.Add(new KeyValue($"titlekek_{i:x2}", 0x10, set => set.Titlekeks[i]));
|
keys.Add(new KeyValue($"titlekek_{i:x2}", 0x10, set => set.TitleKeks[i]));
|
||||||
keys.Add(new KeyValue($"key_area_key_application_{i:x2}", 0x10, set => set.KeyAreaKeys[i][0]));
|
keys.Add(new KeyValue($"key_area_key_application_{i:x2}", 0x10, set => set.KeyAreaKeys[i][0]));
|
||||||
keys.Add(new KeyValue($"key_area_key_ocean_{i:x2}", 0x10, set => set.KeyAreaKeys[i][1]));
|
keys.Add(new KeyValue($"key_area_key_ocean_{i:x2}", 0x10, set => set.KeyAreaKeys[i][1]));
|
||||||
keys.Add(new KeyValue($"key_area_key_system_{i:x2}", 0x10, set => set.KeyAreaKeys[i][2]));
|
keys.Add(new KeyValue($"key_area_key_system_{i:x2}", 0x10, set => set.KeyAreaKeys[i][2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int slot = 0; slot < 3; slot++)
|
for (int slot = 0; slot < 4; slot++)
|
||||||
{
|
{
|
||||||
int i = slot;
|
int i = slot;
|
||||||
keys.Add(new KeyValue($"bis_key_source_{i:x2}", 0x20, set => set.BisKeySource[i]));
|
keys.Add(new KeyValue($"bis_key_source_{i:x2}", 0x20, set => set.BisKeySource[i]));
|
||||||
|
@ -564,7 +593,8 @@ namespace LibHac
|
||||||
new KeyValue("secure_boot_key", 0x10, set => set.SecureBootKey),
|
new KeyValue("secure_boot_key", 0x10, set => set.SecureBootKey),
|
||||||
new KeyValue("tsec_key", 0x10, set => set.TsecKey),
|
new KeyValue("tsec_key", 0x10, set => set.TsecKey),
|
||||||
new KeyValue("device_key", 0x10, set => set.DeviceKey),
|
new KeyValue("device_key", 0x10, set => set.DeviceKey),
|
||||||
new KeyValue("sd_seed", 0x10, set => set.SdSeed)
|
new KeyValue("sd_seed", 0x10, set => set.SdSeed),
|
||||||
|
new KeyValue("save_mac_key", 0x10, set => set.SaveMacKey)
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int slot = 0; slot < 0x20; slot++)
|
for (int slot = 0; slot < 0x20; slot++)
|
||||||
|
|
|
@ -48,13 +48,13 @@ namespace LibHac
|
||||||
}
|
}
|
||||||
else if (keyset.TitleKeys.TryGetValue(Header.RightsId, out byte[] titleKey))
|
else if (keyset.TitleKeys.TryGetValue(Header.RightsId, out byte[] titleKey))
|
||||||
{
|
{
|
||||||
if (keyset.Titlekeks[CryptoType].IsEmpty())
|
if (keyset.TitleKeks[CryptoType].IsEmpty())
|
||||||
{
|
{
|
||||||
MissingKeyName = $"titlekek_{CryptoType:x2}";
|
MissingKeyName = $"titlekek_{CryptoType:x2}";
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleKey = titleKey;
|
TitleKey = titleKey;
|
||||||
Crypto.DecryptEcb(keyset.Titlekeks[CryptoType], titleKey, TitleKeyDec, 0x10);
|
Crypto.DecryptEcb(keyset.TitleKeks[CryptoType], titleKey, TitleKeyDec, 0x10);
|
||||||
DecryptedKeys[2] = TitleKeyDec;
|
DecryptedKeys[2] = TitleKeyDec;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -424,6 +424,8 @@ namespace LibHac
|
||||||
case 3: return "4.0.0-4.1.0";
|
case 3: return "4.0.0-4.1.0";
|
||||||
case 4: return "5.0.0-5.1.0";
|
case 4: return "5.0.0-5.1.0";
|
||||||
case 5: return "6.0.0-6.0.1";
|
case 5: return "6.0.0-6.0.1";
|
||||||
|
case 6: return "6.2.0";
|
||||||
|
case 7: return "7.0.0";
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue