Make sure the title key for an NCA exists when loading

This commit is contained in:
Alex Barney 2018-09-22 18:48:44 -05:00
parent ab565fe83e
commit 34c3ffd37e
5 changed files with 155 additions and 4 deletions

View file

@ -503,4 +503,11 @@ namespace LibHac
}
}
}
public enum KeyType
{
Common,
Unique,
Title
}
}

49
LibHac/LibHacException.cs Normal file
View file

@ -0,0 +1,49 @@
using System;
using System.Runtime.Serialization;
namespace LibHac
{
/// <summary>
/// This is the exception that is thrown when an error occurs
/// </summary>
[Serializable]
public class LibHacException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="LibHacException"/> class.
/// </summary>
public LibHacException()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LibHacException"/> class with a specified error message.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public LibHacException(string message)
: base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LibHacException"/> class with a specified error message
/// and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
public LibHacException(string message, Exception innerException)
: base(message, innerException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LibHacException"/> class with serialized data.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="StreamingContext"/> that contains contextual information about the source or destination.</param>
protected LibHacException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}

View file

@ -0,0 +1,79 @@
using System;
using System.Runtime.Serialization;
namespace LibHac
{
/// <summary>
/// This is the exception that is thrown when an action requires a key that is not found in the provided keyset.
/// </summary>
[Serializable]
public class MissingKeyException : LibHacException, ISerializable
{
/// <summary>
/// The name of the key that is missing.
/// </summary>
public string Name { get; }
/// <summary>
/// The type of the key that is missing.
/// </summary>
public KeyType Type { get; }
/// <summary>
/// Initializes a new instance of the <see cref="MissingKeyException"/> class with a specified error message,
/// information about the missing key and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="name">The name of the key that is missing, or the rights ID of the missing key if <paramref name="keyType"/> is <see cref="KeyType.Title"/></param>
/// <param name="keyType">The <see cref="KeyType"/> of the key that is missing.</param>
public MissingKeyException(string message, string name, KeyType keyType)
: base(message)
{
Name = name;
Type = keyType;
}
/// <summary>
/// Initializes a new instance of the <see cref="MissingKeyException"/> class.
/// </summary>
public MissingKeyException()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MissingKeyException"/> class with a specified error message.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
public MissingKeyException(string message)
: base(message)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MissingKeyException"/> class with a specified error message
/// and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
public MissingKeyException(string message, Exception innerException)
: base(message, innerException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MissingKeyException"/> class with serialized data.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="StreamingContext"/> that contains contextual information about the source or destination.</param>
protected MissingKeyException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue(nameof(Name), Name);
}
}
}

View file

@ -49,6 +49,10 @@ namespace LibHac
Crypto.DecryptEcb(keyset.Titlekeks[CryptoType], titleKey, TitleKeyDec, 0x10);
DecryptedKeys[2] = TitleKeyDec;
}
else
{
throw new MissingKeyException("A required key is missing.", $"{Header.RightsId.ToHexString()}", KeyType.Title);
}
}
for (int i = 0; i < 4; i++)

View file

@ -87,12 +87,22 @@ namespace LibHac
}
nca.NcaId = Path.GetFileNameWithoutExtension(file);
var extention = nca.Header.ContentType == ContentType.Meta ? ".cnmt.nca" : ".nca";
nca.Filename = nca.NcaId + extention;
var extension = nca.Header.ContentType == ContentType.Meta ? ".cnmt.nca" : ".nca";
nca.Filename = nca.NcaId + extension;
}
catch (MissingKeyException ex)
{
if (ex.Name == null)
{ Console.WriteLine($"{ex.Message} File:\n{file}"); }
else
{
string name = ex.Type == KeyType.Title ? $"Title key for rights ID {ex.Name}" : ex.Name;
Console.WriteLine($"{ex.Message}\nKey: {name}\nFile: {file}");
}
}
catch (Exception ex)
{
Console.WriteLine($"{ex.Message} {file}");
Console.WriteLine($"{ex.Message} File: {file}");
}
if (nca?.NcaId != null) Ncas.Add(nca.NcaId, nca);
@ -101,6 +111,8 @@ namespace LibHac
private void OpenAllSaves()
{
if (SaveDir == null) return;
string[] files = Fs.GetFileSystemEntries(SaveDir, "*");
foreach (string file in files)
@ -118,7 +130,7 @@ namespace LibHac
}
catch (Exception ex)
{
Console.WriteLine($"{ex.Message} {file}");
Console.WriteLine($"{ex.Message} File: {file}");
}
if (save != null && saveName != null)