コード例 #1
0
ファイル: ExternalKeySet.cs プロジェクト: ckurtz22/LibHac
 public bool Remove(RightsId rightsId)
 {
     lock (_locker)
     {
         return(ExternalKeys.Remove(rightsId));
     }
 }
コード例 #2
0
        public byte[] GetDecryptedTitleKey()
        {
            int keyRevision = Util.GetMasterKeyRevision(Header.KeyGeneration);

            byte[] titleKek = Keyset.TitleKeks[keyRevision];

            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.IsEmpty())
            {
                string keyName = $"titlekek_{keyRevision:x2}";
                throw new MissingKeyException("Unable to decrypt title key.", keyName, KeyType.Common);
            }

            byte[] encryptedKey = accessKey.Value.ToArray();
            var    decryptedKey = new byte[CryptoOld.Aes128Size];

            CryptoOld.DecryptEcb(titleKek, encryptedKey, decryptedKey, CryptoOld.Aes128Size);

            return(decryptedKey);
        }
コード例 #3
0
ファイル: Nca.cs プロジェクト: garoxas/LibHac
        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);
        }
コード例 #4
0
ファイル: ExternalKeySet.cs プロジェクト: ckurtz22/LibHac
 public bool Contains(RightsId rightsId)
 {
     lock (_locker)
     {
         return(ExternalKeys.ContainsKey(rightsId));
     }
 }
コード例 #5
0
ファイル: ExternalKeySet.cs プロジェクト: ckurtz22/LibHac
        public Result Get(RightsId rightsId, out AccessKey key)
        {
            lock (_locker)
            {
                if (ExternalKeys.TryGetValue(rightsId, out key))
                {
                    return(Result.Success);
                }

                return(ResultFs.ExternalKeyNotFound.Log());
            }
        }
コード例 #6
0
ファイル: ExternalKeySet.cs プロジェクト: garoxas/LibHac
        public Result Get(RightsId rightsId, out AccessKey key)
        {
            lock (_locker)
            {
                if (ExternalKeys.TryGetValue(rightsId, out key))
                {
                    return(Result.Success);
                }

                return(ResultFs.NcaExternalKeyUnavailable.Log());
            }
        }
コード例 #7
0
ファイル: ExternalKeySet.cs プロジェクト: ckurtz22/LibHac
        public Result Add(RightsId rightsId, AccessKey key)
        {
            lock (_locker)
            {
                if (ExternalKeys.TryGetValue(rightsId, out AccessKey existingKey))
                {
                    if (key == existingKey)
                    {
                        return(Result.Success);
                    }

                    return(ResultFs.ExternalKeyAlreadyRegistered.Log());
                }

                ExternalKeys.Add(rightsId, key);
            }

            return(Result.Success);
        }
コード例 #8
0
ファイル: ExternalKeyReader.cs プロジェクト: garoxas/LibHac
        /// <summary>
        /// Loads title keys from a <see cref="TextReader"/> into an existing <see cref="KeySet"/>.
        /// </summary>
        /// <param name="keySet">The <see cref="KeySet"/> where the loaded keys will be placed.</param>
        /// <param name="reader">A <see cref="Stream"/> containing the keys to load.</param>
        /// <param name="logger">An optional logger that key-parsing errors will be written to.</param>
        public static void ReadTitleKeys(KeySet keySet, Stream reader, IProgressReport logger = null)
        {
            if (reader == null)
            {
                return;
            }

            using var streamReader = new StreamReader(reader);
            Span <char> buffer = stackalloc char[ReadBufferSize];
            var         ctx    = new KvPairReaderContext(streamReader, buffer);

            // Estimate the number of keys by assuming each line is about 69 bytes.
            // Subtract 2 from that so we estimate slightly high.
            keySet.ExternalKeySet.EnsureCapacity((int)reader.Length / 67);

            while (true)
            {
                ReaderStatus status = GetKeyValuePair(ref ctx);

                if (status == ReaderStatus.Error)
                {
                    logger?.LogMessage($"Invalid line in key data: \"{ctx.CurrentKey.ToString()}\"");
                    Debugger.Break();
                }
                else if (status == ReaderStatus.ReadKey)
                {
                    if (ctx.CurrentKey.Length != TitleKeySize * 2)
                    {
                        logger?.LogMessage($"Rights ID {ctx.CurrentKey.ToString()} has incorrect size {ctx.CurrentKey.Length}. (Expected {TitleKeySize * 2})");
                        continue;
                    }

                    if (ctx.CurrentValue.Length != TitleKeySize * 2)
                    {
                        logger?.LogMessage($"Title key {ctx.CurrentValue.ToString()} has incorrect size {ctx.CurrentValue.Length}. (Expected {TitleKeySize * 2})");
                        continue;
                    }

                    var rightsId = new RightsId();
                    var titleKey = new AccessKey();

                    if (!StringUtils.TryFromHexString(ctx.CurrentKey, SpanHelpers.AsByteSpan(ref rightsId)))
                    {
                        logger?.LogMessage($"Invalid rights ID \"{ctx.CurrentKey.ToString()}\" in title key file");
                        continue;
                    }

                    if (!StringUtils.TryFromHexString(ctx.CurrentValue, SpanHelpers.AsByteSpan(ref titleKey)))
                    {
                        logger?.LogMessage($"Invalid title key \"{ctx.CurrentValue.ToString()}\" in title key file");
                        continue;
                    }

                    keySet.ExternalKeySet.Add(rightsId, titleKey).ThrowIfFailure();
                }
                else if (status == ReaderStatus.Finished)
                {
                    break;
                }
            }
        }
コード例 #9
0
        private void BuildChildItems(PartitionFileSystemItemBase parentItem)
        {
            try
            {
                var partitionFileSystem = parentItem.PartitionFileSystem;

                var remainingEntries = new List <PartitionFileEntry>();

                // First loop on *.tik files to inject title keys in KeySet
                foreach (var partitionFileEntry in partitionFileSystem.Files)
                {
                    var fileName = partitionFileEntry.Name;
                    if (!fileName.EndsWith(".tik", StringComparison.OrdinalIgnoreCase))
                    {
                        remainingEntries.Add(partitionFileEntry);
                        continue;
                    }

                    IFile file;
                    try
                    {
                        file = partitionFileSystem.OpenFile(partitionFileEntry, OpenMode.Read);
                    }
                    catch (Exception ex)
                    {
                        OnLoadingException(ex, parentItem);

                        var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToOpenPartitionFile.SafeFormat(ex.Message);
                        parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                        _logger.LogError(ex, message);
                        continue;
                    }

                    Ticket ticket;
                    try
                    {
                        using var asStream = file.AsStream();
                        ticket             = new Ticket(asStream);
                    }
                    catch (Exception ex)
                    {
                        OnLoadingException(ex, parentItem);

                        var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadTicketFile.SafeFormat(ex.Message);
                        parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                        _logger.LogError(ex, message);
                        continue;
                    }

                    var ticketItem = new TicketItem(ticket, partitionFileEntry, file, parentItem);

                    try
                    {
                        var rightsId  = new RightsId(ticket.RightsId);
                        var accessKey = new AccessKey(ticket.TitleKeyBlock);

                        ticketItem.RightsId  = rightsId;
                        ticketItem.AccessKey = accessKey;

                        if (parentItem.KeySet.ExternalKeySet.Get(rightsId, out var existingAccessKey) == Result.Success)
                        {
                            // Here RightID key is already defined
                            if (existingAccessKey != accessKey)
                            {
                                // Replaces the RightID key with the one defined in the ticket
                                parentItem.KeySet.ExternalKeySet.Remove(rightsId);
                                parentItem.KeySet.ExternalKeySet.Add(rightsId, accessKey).ThrowIfFailure();
                                _logger.LogWarning(LocalizationManager.Instance.Current.Keys.LoadingWarning_TitleIdKeyReplaced.SafeFormat(rightsId.ToString(), accessKey.ToString(), fileName, existingAccessKey));
                            }
                            else
                            {
                                _logger.LogDebug(LocalizationManager.Instance.Current.Keys.LoadingDebug_TitleIdKeyAlreadyExists.SafeFormat(rightsId.ToString(), accessKey.ToString(), fileName));
                            }
                        }
                        else
                        {
                            parentItem.KeySet.ExternalKeySet.Add(rightsId, accessKey).ThrowIfFailure();
                            _logger.LogInformation(LocalizationManager.Instance.Current.Keys.LoadingInfo_TitleIdKeySuccessfullyInjected.SafeFormat(rightsId.ToString(), accessKey.ToString(), fileName));
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadTitleIdKey.SafeFormat(fileName, ex.Message));
                    }

                    parentItem.TicketChildItems.Add(ticketItem);
                }

                foreach (var partitionFileEntry in remainingEntries)
                {
                    IFile file;
                    try
                    {
                        file = partitionFileSystem.OpenFile(partitionFileEntry, OpenMode.Read);
                    }
                    catch (Exception ex)
                    {
                        OnLoadingException(ex, parentItem);

                        var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToOpenPartitionFile.SafeFormat(ex.Message);
                        parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                        _logger.LogError(ex, message);
                        continue;
                    }

                    var fileName = partitionFileEntry.Name;
                    if (fileName.EndsWith(".nca", StringComparison.OrdinalIgnoreCase) || fileName.EndsWith(".ncz", StringComparison.OrdinalIgnoreCase))
                    {
                        Nca nca;
                        try
                        {
                            nca = new Nca(parentItem.KeySet, new FileStorage(file));
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadNcaFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        var ncaItem = new NcaItem(nca, partitionFileEntry, file, parentItem);
                        BuildChildItems(ncaItem);
                        parentItem.NcaChildItems.Add(ncaItem);
                    }
                    else
                    {
                        var partitionFileEntryItem = new PartitionFileEntryItem(partitionFileEntry, file, parentItem);
                        parentItem.PartitionFileEntryChildItems.Add(partitionFileEntryItem);
                    }
                }
            }
            catch (Exception ex)
            {
                OnLoadingException(ex, parentItem);

                var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadPartitionFileSystemContent.SafeFormat(ex.Message);
                parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                _logger.LogError(ex, message);
            }
        }