Example #1
0
        public void DeriveSdCardKeys()
        {
            var sdKek = new byte[0x10];

            GenerateKek(MasterKeys[0], SdCardKekSource, sdKek, AesKekGenerationSource, AesKeyGenerationSource);

            for (int k = 0; k < SdCardKeyIdCount; k++)
            {
                for (int i = 0; i < 0x20; i++)
                {
                    SdCardKeySourcesSpecific[k][i] = (byte)(SdCardKeySources[k][i] ^ SdSeed[i & 0xF]);
                }
            }

            for (int k = 0; k < SdCardKeyIdCount; k++)
            {
                Aes.DecryptEcb128(SdCardKeySourcesSpecific[k], SdCardKeys[k], sdKek);
            }

            // Derive sd card save key
            if (!SaveMacSdCardKekSource.IsEmpty() && !SaveMacSdCardKeySource.IsEmpty())
            {
                var keySource = new byte[0x10];

                for (int i = 0; i < 0x10; i++)
                {
                    keySource[i] = (byte)(SaveMacSdCardKeySource[i] ^ SdSeed[i]);
                }

                GenerateKek(MasterKeys[0], SaveMacSdCardKekSource, sdKek, AesKekGenerationSource, null);
                Aes.DecryptEcb128(keySource, SaveMacSdCardKey, sdKek);
            }
        }
Example #2
0
        private void DecryptKeyblobs(IProgressReport logger = null)
        {
            var cmac         = new byte[0x10];
            var expectedCmac = new byte[0x10];
            var counter      = new byte[0x10];

            for (int i = 0; i < UsedKeyblobCount; i++)
            {
                if (KeyblobKeys[i].IsEmpty() || KeyblobMacKeys[i].IsEmpty() || EncryptedKeyblobs[i].IsEmpty())
                {
                    continue;
                }

                Array.Copy(EncryptedKeyblobs[i], expectedCmac, 0x10);
                Aes.CalculateCmac(cmac, EncryptedKeyblobs[i].AsSpan(0x10, 0xA0), KeyblobMacKeys[i]);

                if (!Utilities.ArraysEqual(cmac, expectedCmac))
                {
                    logger?.LogMessage($"Warning: Keyblob MAC {i:x2} is invalid. Are SBK/TSEC key correct?");
                }

                Array.Copy(EncryptedKeyblobs[i], 0x10, counter, 0, 0x10);

                Aes.DecryptCtr128(EncryptedKeyblobs[i].AsSpan(0x20), Keyblobs[i], KeyblobKeys[i], counter);
            }
        }
Example #3
0
        private void DeriveKeyblobKeys()
        {
            if (SecureBootKey.IsEmpty() || TsecKey.IsEmpty())
            {
                return;
            }

            bool haveKeyblobMacKeySource = !MasterKeySource.IsEmpty();
            var  temp = new byte[0x10];

            for (int i = 0; i < UsedKeyblobCount; i++)
            {
                if (KeyblobKeySources[i].IsEmpty())
                {
                    continue;
                }

                Aes.DecryptEcb128(KeyblobKeySources[i], temp, TsecKey);
                Aes.DecryptEcb128(temp, KeyblobKeys[i], SecureBootKey);

                if (!haveKeyblobMacKeySource)
                {
                    continue;
                }

                Aes.DecryptEcb128(KeyblobMacKeySource, KeyblobMacKeys[i], KeyblobKeys[i]);
            }
        }
Example #4
0
        private void Derive620MasterKeks()
        {
            for (int i = UsedKeyblobCount; i < 0x20; i++)
            {
                if (TsecRootKeys[i - UsedKeyblobCount].IsEmpty() || MasterKekSources[i].IsEmpty())
                {
                    continue;
                }

                Aes.DecryptEcb128(MasterKekSources[i], MasterKeks[i], TsecRootKeys[i - UsedKeyblobCount]);
            }
        }
Example #5
0
        private void DeriveNcaHeaderKey()
        {
            if (HeaderKekSource.IsEmpty() || HeaderKeySource.IsEmpty() || MasterKeys[0].IsEmpty())
            {
                return;
            }

            var headerKek = new byte[0x10];

            GenerateKek(MasterKeys[0], HeaderKekSource, headerKek, AesKekGenerationSource,
                        AesKeyGenerationSource);
            Aes.DecryptEcb128(HeaderKeySource, HeaderKey, headerKek);
        }
Example #6
0
        private void DerivePerConsoleKeys()
        {
            var kek = new byte[0x10];

            // Derive the device key
            if (!PerConsoleKeySource.IsEmpty() && !KeyblobKeys[0].IsEmpty())
            {
                Aes.DecryptEcb128(PerConsoleKeySource, DeviceKey, KeyblobKeys[0]);
            }

            // Derive save key
            if (!SaveMacKekSource.IsEmpty() && !SaveMacKeySource.IsEmpty() && !DeviceKey.IsEmpty())
            {
                GenerateKek(DeviceKey, SaveMacKekSource, kek, AesKekGenerationSource, null);
                Aes.DecryptEcb128(SaveMacKeySource, SaveMacKey, kek);
            }

            // Derive BIS keys
            if (DeviceKey.IsEmpty() ||
                BisKekSource.IsEmpty() ||
                AesKekGenerationSource.IsEmpty() ||
                AesKeyGenerationSource.IsEmpty() ||
                RetailSpecificAesKeySource.IsEmpty())
            {
                return;
            }

            // If the user doesn't provide bis_key_source_03 we can assume it's the same as bis_key_source_02
            if (BisKeySource[3].IsEmpty() && !BisKeySource[2].IsEmpty())
            {
                Array.Copy(BisKeySource[2], BisKeySource[3], 0x20);
            }

            Aes.DecryptEcb128(RetailSpecificAesKeySource, kek, DeviceKey);
            if (!BisKeySource[0].IsEmpty())
            {
                Aes.DecryptEcb128(BisKeySource[0], BisKeys[0], kek);
            }

            GenerateKek(DeviceKey, BisKekSource, kek, AesKekGenerationSource, AesKeyGenerationSource);

            for (int i = 1; i < 4; i++)
            {
                if (!BisKeySource[i].IsEmpty())
                {
                    Aes.DecryptEcb128(BisKeySource[i], BisKeys[i], kek);
                }
            }
        }
Example #7
0
        public static void GenerateKek(byte[] key, byte[] src, byte[] dest, byte[] kekSeed, byte[] keySeed)
        {
            var kek    = new byte[Aes.KeySize128];
            var srcKek = new byte[Aes.KeySize128];

            Aes.DecryptEcb128(kekSeed, kek, key);
            Aes.DecryptEcb128(src, srcKek, kek);

            if (keySeed != null)
            {
                Aes.DecryptEcb128(keySeed, dest, srcKek);
            }
            else
            {
                Array.Copy(srcKek, dest, Aes.KeySize128);
            }
        }
Example #8
0
        private static void GenerateKek(ReadOnlySpan <byte> key, ReadOnlySpan <byte> src, Span <byte> dest, ReadOnlySpan <byte> kekSeed, ReadOnlySpan <byte> keySeed)
        {
            Span <byte> kek    = stackalloc byte[0x10];
            Span <byte> srcKek = stackalloc byte[0x10];

            Aes.DecryptEcb128(kekSeed, kek, key);
            Aes.DecryptEcb128(src, srcKek, kek);

            if (!keySeed.IsEmpty)
            {
                Aes.DecryptEcb128(keySeed, dest, srcKek);
            }
            else
            {
                srcKek.CopyTo(dest);
            }
        }
Example #9
0
        private void DeriveMasterKeys()
        {
            if (MasterKeySource.IsEmpty())
            {
                return;
            }

            for (int i = 0; i < 0x20; i++)
            {
                if (MasterKeks[i].IsEmpty())
                {
                    continue;
                }

                Aes.DecryptEcb128(MasterKeySource, MasterKeys[i], MasterKeks[i]);
            }
        }
Example #10
0
        private void DerivePerFirmwareKeys()
        {
            bool haveKakSource0        = !KeyAreaKeyApplicationSource.IsEmpty();
            bool haveKakSource1        = !KeyAreaKeyOceanSource.IsEmpty();
            bool haveKakSource2        = !KeyAreaKeySystemSource.IsEmpty();
            bool haveTitleKekSource    = !TitleKekSource.IsEmpty();
            bool havePackage2KeySource = !Package2KeySource.IsEmpty();

            for (int i = 0; i < 0x20; i++)
            {
                if (MasterKeys[i].IsEmpty())
                {
                    continue;
                }

                if (haveKakSource0)
                {
                    GenerateKek(MasterKeys[i], KeyAreaKeyApplicationSource, KeyAreaKeys[i][0],
                                AesKekGenerationSource, AesKeyGenerationSource);
                }

                if (haveKakSource1)
                {
                    GenerateKek(MasterKeys[i], KeyAreaKeyOceanSource, KeyAreaKeys[i][1],
                                AesKekGenerationSource, AesKeyGenerationSource);
                }

                if (haveKakSource2)
                {
                    GenerateKek(MasterKeys[i], KeyAreaKeySystemSource, KeyAreaKeys[i][2],
                                AesKekGenerationSource, AesKeyGenerationSource);
                }

                if (haveTitleKekSource)
                {
                    Aes.DecryptEcb128(TitleKekSource, TitleKeks[i], MasterKeys[i]);
                }

                if (havePackage2KeySource)
                {
                    Aes.DecryptEcb128(Package2KeySource, Package2Keys[i], MasterKeys[i]);
                }
            }
        }