Example #1
0
        public byte[] GetDecryptedTitleKey()
        {
            int keyRevision = Utilities.GetMasterKeyRevision(Header.KeyGeneration);

            byte[] titleKek = KeySet.TitleKeks[keyRevision].DataRo.ToArray();

            var rightsId = new RightsId(Header.RightsId);

            if (KeySet.ExternalKeySet.Get(rightsId, out AccessKey accessKey).IsFailure())
            {
                throw new MissingKeyException("Missing NCA title key.", rightsId.ToString(), KeyType.Title);
            }

            if (titleKek.IsZeros())
            {
                string keyName = $"titlekek_{keyRevision:x2}";
                throw new MissingKeyException("Unable to decrypt title key.", keyName, KeyType.Common);
            }

            byte[] encryptedKey = accessKey.Value.ToArray();
            byte[] decryptedKey = new byte[Aes.KeySize128];

            Aes.DecryptEcb128(encryptedKey, decryptedKey, titleKek);

            return(decryptedKey);
        }
Example #2
0
        private static void DeriveKeyBlobKeys(KeySet s)
        {
            if (s.SecureBootKey.IsZeros() || s.TsecKey.IsZeros())
            {
                return;
            }

            bool haveKeyBlobMacKeySource = !s.MasterKeySource.IsZeros();
            var  temp = new AesKey();

            for (int i = 0; i < KeySet.UsedKeyBlobCount; i++)
            {
                if (s.KeyBlobKeySources[i].IsZeros())
                {
                    continue;
                }

                Aes.DecryptEcb128(s.KeyBlobKeySources[i], temp, s.TsecKey);
                Aes.DecryptEcb128(temp, s.KeyBlobKeys[i], s.SecureBootKey);

                if (!haveKeyBlobMacKeySource)
                {
                    continue;
                }

                Aes.DecryptEcb128(s.KeyBlobMacKeySource, s.KeyBlobMacKeys[i], s.KeyBlobKeys[i]);
            }
        }
Example #3
0
        public byte[] GetDecryptedKey(int index)
        {
            if (index < 0 || index > 3)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            // Handle old NCA0s that use different key area encryption
            if (Header.FormatVersion == NcaVersion.Nca0FixedKey || Header.FormatVersion == NcaVersion.Nca0RsaOaep)
            {
                return(GetDecryptedKeyAreaNca0().AsSpan(0x10 * index, 0x10).ToArray());
            }

            int keyRevision = Utilities.GetMasterKeyRevision(Header.KeyGeneration);

            byte[] keyAreaKey = KeySet.KeyAreaKeys[keyRevision][Header.KeyAreaKeyIndex].DataRo.ToArray();

            if (keyAreaKey.IsZeros())
            {
                string keyName = $"key_area_key_{KakNames[Header.KeyAreaKeyIndex]}_{keyRevision:x2}";
                throw new MissingKeyException("Unable to decrypt NCA section.", keyName, KeyType.Common);
            }

            byte[] encryptedKey = Header.GetEncryptedKey(index).ToArray();
            byte[] decryptedKey = new byte[Aes.KeySize128];

            Aes.DecryptEcb128(encryptedKey, decryptedKey, keyAreaKey);

            return(decryptedKey);
        }
Example #4
0
        public static void DeriveSdCardKeys(KeySet s)
        {
            var sdKek   = new AesKey();
            var tempKey = new AesXtsKey();

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

            for (int k = 0; k < KeySet.SdCardKeyIdCount; k++)
            {
                for (int i = 0; i < 4; i++)
                {
                    tempKey.Data64[i] = s.SdCardKeySources[k].Data64[i] ^ s.SdCardEncryptionSeed.Data64[i & 1];
                }

                tempKey.Data64[0] = s.SdCardKeySources[k].Data64[0] ^ s.SdCardEncryptionSeed.Data64[0];
                tempKey.Data64[1] = s.SdCardKeySources[k].Data64[1] ^ s.SdCardEncryptionSeed.Data64[1];
                tempKey.Data64[2] = s.SdCardKeySources[k].Data64[2] ^ s.SdCardEncryptionSeed.Data64[0];
                tempKey.Data64[3] = s.SdCardKeySources[k].Data64[3] ^ s.SdCardEncryptionSeed.Data64[1];

                Aes.DecryptEcb128(tempKey, s.SdCardEncryptionKeys[k], sdKek);
            }

            // Derive sd card save key
            if (!s.SeedUniqueSaveMacKekSource.IsZeros() && !s.SeedUniqueSaveMacKeySource.IsZeros())
            {
                var keySource = new AesKey();

                keySource.Data64[0] = s.SeedUniqueSaveMacKeySource.Data64[0] ^ s.SdCardEncryptionSeed.Data64[0];
                keySource.Data64[1] = s.SeedUniqueSaveMacKeySource.Data64[1] ^ s.SdCardEncryptionSeed.Data64[1];

                GenerateKek(s.MasterKeys[0], s.SeedUniqueSaveMacKekSource, sdKek, s.AesKekGenerationSource, null);
                Aes.DecryptEcb128(keySource, s.SeedUniqueSaveMacKey, sdKek);
            }
        }
Example #5
0
        private static void PopulateOldMasterKeys(KeySet s)
        {
            ReadOnlySpan <AesKey> keyVectors = MasterKeyVectors(s);

            // Find the newest master key we have
            int newestMasterKey = -1;

            for (int i = keyVectors.Length - 1; i >= 0; i--)
            {
                if (!s.MasterKeys[i].IsZeros())
                {
                    newestMasterKey = i;
                    break;
                }
            }

            if (newestMasterKey == -1)
            {
                return;
            }

            // Don't populate old master keys unless the newest master key is valid
            if (!TestKeyGeneration(s, newestMasterKey))
            {
                return;
            }

            // Decrypt all previous master keys
            for (int i = newestMasterKey; i > 0; i--)
            {
                Aes.DecryptEcb128(keyVectors[i], s.MasterKeys[i - 1], s.MasterKeys[i]);
            }
        }
Example #6
0
        private static void DerivePerConsoleKeys(KeySet s)
        {
            // Todo: Dev and newer key generations
            var kek = new AesKey();

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

            // Derive device-unique save keys
            for (int i = 0; i < s.DeviceUniqueSaveMacKeySources.Length; i++)
            {
                if (!s.DeviceUniqueSaveMacKekSource.IsZeros() && !s.DeviceUniqueSaveMacKeySources[i].IsZeros() &&
                    !s.DeviceKey.IsZeros())
                {
                    GenerateKek(s.DeviceKey, s.DeviceUniqueSaveMacKekSource, kek, s.AesKekGenerationSource, null);
                    Aes.DecryptEcb128(s.DeviceUniqueSaveMacKeySources[i], s.DeviceUniqueSaveMacKeys[i], kek);
                }
            }

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

            // If the user doesn't provide bis_key_source_03 we can assume it's the same as bis_key_source_02
            if (s.BisKeySources[3].IsZeros() && !s.BisKeySources[2].IsZeros())
            {
                s.BisKeySources[3] = s.BisKeySources[2];
            }

            Aes.DecryptEcb128(s.RetailSpecificAesKeySource, kek, s.DeviceKey);
            if (!s.BisKeySources[0].IsZeros())
            {
                Aes.DecryptEcb128(s.BisKeySources[0], s.BisKeys[0], kek);
            }

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

            for (int i = 1; i < 4; i++)
            {
                if (!s.BisKeySources[i].IsZeros())
                {
                    Aes.DecryptEcb128(s.BisKeySources[i], s.BisKeys[i], kek);
                }
            }
        }
Example #7
0
        private static void DeriveNcaHeaderKey(KeySet s)
        {
            if (s.HeaderKekSource.IsZeros() || s.HeaderKeySource.IsZeros() || s.MasterKeys[0].IsZeros())
            {
                return;
            }

            var headerKek = new AesKey();

            GenerateKek(s.MasterKeys[0], s.HeaderKekSource, headerKek, s.AesKekGenerationSource,
                        s.AesKeyGenerationSource);
            Aes.DecryptEcb128(s.HeaderKeySource, s.HeaderKey, headerKek);
        }
Example #8
0
        private static void Derive620MasterKeks(KeySet s)
        {
            for (int i = KeySet.UsedKeyBlobCount; i < KeySet.KeyRevisionCount; i++)
            {
                // Key revisions >= 8 all use the same TSEC root key
                int tsecRootKeyIndex = Math.Min(i, 8) - KeySet.UsedKeyBlobCount;
                if (s.TsecRootKeys[tsecRootKeyIndex].IsZeros() || s.MasterKekSources[i].IsZeros())
                {
                    continue;
                }

                Aes.DecryptEcb128(s.MasterKekSources[i], s.MasterKeks[i], s.TsecRootKeys[tsecRootKeyIndex]);
            }
        }
Example #9
0
        private static void DeriveMasterKeys(KeySet s)
        {
            if (s.MasterKeySource.IsZeros())
            {
                return;
            }

            for (int i = 0; i < KeySet.KeyRevisionCount; i++)
            {
                if (s.MasterKeks[i].IsZeros())
                {
                    continue;
                }

                Aes.DecryptEcb128(s.MasterKeySource, s.MasterKeys[i], s.MasterKeks[i]);
            }
        }
Example #10
0
        private static void GenerateKek(ReadOnlySpan <byte> key, ReadOnlySpan <byte> src, Span <byte> dest,
                                        ReadOnlySpan <byte> kekSeed, ReadOnlySpan <byte> keySeed)
        {
            var kek    = new AesKey();
            var srcKek = new AesKey();

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

            if (!keySeed.IsZeros())
            {
                Aes.DecryptEcb128(keySeed, dest, srcKek);
            }
            else
            {
                srcKek.Data.CopyTo(dest);
            }
        }
Example #11
0
        /// <summary>
        /// Check if the master key of the specified generation is correct.
        /// </summary>
        /// <param name="s">The <see cref="KeySet"/> to test.</param>
        /// <param name="generation">The generation to test.</param>
        /// <returns><see langword="true"/> if the key is correct.</returns>
        private static bool TestKeyGeneration(KeySet s, int generation)
        {
            ReadOnlySpan <AesKey> keyVectors = MasterKeyVectors(s);

            // Decrypt the vector chain until we get Master Key 0
            AesKey key = s.MasterKeys[generation];

            for (int i = generation; i > 0; i--)
            {
                Aes.DecryptEcb128(keyVectors[i], key, key);
            }

            // Decrypt the zeros with Master Key 0
            Aes.DecryptEcb128(keyVectors[0], key, key);

            // If we don't get zeros, MasterKeys[generation] is incorrect
            return(key.IsZeros());
        }
Example #12
0
        private static void DerivePerGenerationKeys(KeySet s)
        {
            bool haveKakSource0        = !s.KeyAreaKeyApplicationSource.IsZeros();
            bool haveKakSource1        = !s.KeyAreaKeyOceanSource.IsZeros();
            bool haveKakSource2        = !s.KeyAreaKeySystemSource.IsZeros();
            bool haveTitleKekSource    = !s.TitleKekSource.IsZeros();
            bool havePackage2KeySource = !s.Package2KeySource.IsZeros();

            for (int i = 0; i < KeySet.KeyRevisionCount; i++)
            {
                if (s.MasterKeys[i].IsZeros())
                {
                    continue;
                }

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

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

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

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

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