예제 #1
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;
                }

                Crypto.DecryptEcb(TsecKey, KeyblobKeySources[i], temp, 0x10);
                Crypto.DecryptEcb(SecureBootKey, temp, KeyblobKeys[i], 0x10);

                if (!haveKeyblobMacKeySource)
                {
                    continue;
                }

                Crypto.DecryptEcb(KeyblobKeys[i], KeyblobMacKeySource, KeyblobMacKeys[i], 0x10);
            }
        }
예제 #2
0
파일: Keyset.cs 프로젝트: tiliarou/LibHac
        private void ReadKeyblobs()
        {
            var masterKek = new byte[0x10];

            bool haveMasterKeySource = !MasterKeySource.IsEmpty();

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

                Array.Copy(Keyblobs[i], 0x80, Package1Keys[i], 0, 0x10);

                if (!haveMasterKeySource)
                {
                    continue;
                }

                Array.Copy(Keyblobs[i], masterKek, 0x10);

                Crypto.DecryptEcb(masterKek, MasterKeySource, MasterKeys[i], 0x10);
            }
        }
예제 #3
0
파일: Keyset.cs 프로젝트: CaitSith2/libhac
        public void DeriveSdCardKeys()
        {
            var sdKek = new byte[0x10];

            Crypto.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++)
            {
                Crypto.DecryptEcb(sdKek, SdCardKeySourcesSpecific[k], SdCardKeys[k], 0x20);
            }

            // 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]);
                }

                Crypto.GenerateKek(MasterKeys[0], SaveMacSdCardKekSource, sdKek, AesKekGenerationSource, null);
                Crypto.DecryptEcb(sdKek, keySource, SaveMacSdCardKey, 0x10);
            }
        }
예제 #4
0
        private void Derive620MasterKeks()
        {
            for (int i = UsedKeyblobCount; i < 0x20; i++)
            {
                if (TsecRootKeys[i - UsedKeyblobCount].IsEmpty() || MasterKekSources[i].IsEmpty())
                {
                    continue;
                }

                Crypto.DecryptEcb(TsecRootKeys[i - UsedKeyblobCount], MasterKekSources[i], MasterKeks[i], 0x10);
            }
        }
예제 #5
0
        private void DeriveNcaHeaderKey()
        {
            if (HeaderKekSource.IsEmpty() || HeaderKeySource.IsEmpty() || MasterKeys[0].IsEmpty())
            {
                return;
            }

            var headerKek = new byte[0x10];

            Crypto.GenerateKek(MasterKeys[0], HeaderKekSource, headerKek, AesKekGenerationSource,
                               AesKeyGenerationSource);
            Crypto.DecryptEcb(headerKek, HeaderKeySource, HeaderKey, 0x20);
        }
예제 #6
0
        private void DerivePerConsoleKeys()
        {
            var kek = new byte[0x10];

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

            // Derive save key
            if (!SaveMacKekSource.IsEmpty() && !SaveMacKeySource.IsEmpty() && !DeviceKey.IsEmpty())
            {
                Crypto.GenerateKek(DeviceKey, SaveMacKekSource, kek, AesKekGenerationSource, null);
                Crypto.DecryptEcb(kek, SaveMacKeySource, SaveMacKey, 0x10);
            }

            // 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);
            }

            Crypto.DecryptEcb(DeviceKey, RetailSpecificAesKeySource, kek, 0x10);
            if (!BisKeySource[0].IsEmpty())
            {
                Crypto.DecryptEcb(kek, BisKeySource[0], BisKeys[0], 0x20);
            }

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

            for (int i = 1; i < 4; i++)
            {
                if (!BisKeySource[i].IsEmpty())
                {
                    Crypto.DecryptEcb(kek, BisKeySource[i], BisKeys[i], 0x20);
                }
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
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)
                {
                    Crypto.GenerateKek(MasterKeys[i], KeyAreaKeyApplicationSource, KeyAreaKeys[i][0],
                                       AesKekGenerationSource, AesKeyGenerationSource);
                }

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

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

                if (haveTitleKekSource)
                {
                    Crypto.DecryptEcb(MasterKeys[i], TitleKekSource, TitleKeks[i], 0x10);
                }

                if (havePackage2KeySource)
                {
                    Crypto.DecryptEcb(MasterKeys[i], Package2KeySource, Package2Keys[i], 0x10);
                }
            }
        }
예제 #9
0
        public void DeriveSdCardKeys()
        {
            var sdKek = new byte[0x10];

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

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

            for (int k = 0; k < SdCardKeySourcesSpecific.Length; k++)
            {
                Crypto.DecryptEcb(sdKek, SdCardKeySourcesSpecific[k], SdCardKeys[k], 0x20);
            }
        }
예제 #10
0
파일: Nax0.cs 프로젝트: tiliarou/LibHac
        private void DeriveKeys(Keyset keyset, string sdPath, IStorage storage)
        {
            var validationHashKey = new byte[0x60];

            storage.Read(validationHashKey, 0x20);

            // Try both the NCA and save key sources and pick the one that works
            for (int k = 0; k < 2; k++)
            {
                var naxSpecificKeys = Util.CreateJaggedArray <byte[][]>(2, 0x10);
                var hashKey         = new byte[0x10];
                Array.Copy(keyset.SdCardKeys[k], hashKey, 0x10);

                // Use the sd path to generate the kek for this NAX0
                var    hash        = new HMACSHA256(hashKey);
                byte[] sdPathBytes = Encoding.ASCII.GetBytes(sdPath);
                byte[] checksum    = hash.ComputeHash(sdPathBytes, 0, sdPathBytes.Length);
                Array.Copy(checksum, 0, naxSpecificKeys[0], 0, 0x10);
                Array.Copy(checksum, 0x10, naxSpecificKeys[1], 0, 0x10);

                // Decrypt this NAX0's keys
                Crypto.DecryptEcb(naxSpecificKeys[0], EncKeys[0], Keys[0], 0x10);
                Crypto.DecryptEcb(naxSpecificKeys[1], EncKeys[1], Keys[1], 0x10);
                Array.Copy(Keys[0], 0, Key, 0, 0x10);
                Array.Copy(Keys[1], 0, Key, 0x10, 0x10);

                // Copy the decrypted keys into the NAX0 header and use that for the HMAC key
                // for validating that the keys are correct
                Array.Copy(Keys[0], 0, validationHashKey, 8, 0x10);
                Array.Copy(Keys[1], 0, validationHashKey, 0x18, 0x10);

                var    validationHash = new HMACSHA256(validationHashKey);
                byte[] validationMac  = validationHash.ComputeHash(keyset.SdCardKeys[k], 0x10, 0x10);

                if (Util.ArraysEqual(Hmac, validationMac))
                {
                    return;
                }
            }

            throw new ArgumentException("NAX0 key derivation failed.");
        }
예제 #11
0
파일: Keyset.cs 프로젝트: tiliarou/LibHac
        private void DerivePerConsoleKeys()
        {
            var kek = new byte[0x10];

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

            // Derive save key
            if (!SaveMacKekSource.IsEmpty() && !SaveMacKeySource.IsEmpty() && !DeviceKey.IsEmpty())
            {
                Crypto.GenerateKek(DeviceKey, SaveMacKekSource, kek, AesKekGenerationSource, null);
                Crypto.DecryptEcb(kek, SaveMacKeySource, SaveMacKey, 0x10);
            }

            // Derive BIS keys
            if (DeviceKey.IsEmpty() ||
                BisKeySource[0].IsEmpty() ||
                BisKeySource[1].IsEmpty() ||
                BisKeySource[2].IsEmpty() ||
                BisKekSource.IsEmpty() ||
                AesKekGenerationSource.IsEmpty() ||
                AesKeyGenerationSource.IsEmpty() ||
                RetailSpecificAesKeySource.IsEmpty())
            {
                return;
            }

            Crypto.DecryptEcb(DeviceKey, RetailSpecificAesKeySource, kek, 0x10);
            Crypto.DecryptEcb(kek, BisKeySource[0], BisKeys[0], 0x20);

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

            Crypto.DecryptEcb(kek, BisKeySource[1], BisKeys[1], 0x20);
            Crypto.DecryptEcb(kek, BisKeySource[2], BisKeys[2], 0x20);

            // BIS keys 2 and 3 are the same
            Array.Copy(BisKeys[2], BisKeys[3], 0x20);
        }