Migrate more to split code

This commit is contained in:
Matt Nadareski
2024-10-13 22:10:59 -04:00
parent 5148ba5d83
commit 72afaeb010
2 changed files with 133 additions and 51 deletions

View File

@@ -325,6 +325,33 @@ namespace NDecrypt.N3DS
public static uint GetExeFSSize(NCCHHeader header, uint mediaUnitSize)
=> header.ExeFSSizeInMediaUnits * mediaUnitSize;
/// <summary>
/// Get the size of a partition extended header
/// </summary>
/// <returns>Size of the partition extended header in bytes, 0 on error</returns>
public static uint GetExtendedHeaderSize(Cart cart, int index)
{
// Empty partitions array means no size is available
var partitions = cart.Partitions;
if (partitions == null)
return 0;
// Invalid partition header means no size is available
var header = partitions[index];
if (header == null)
return 0;
// Return the adjusted size
return GetExtendedHeaderSize(header);
}
/// <summary>
/// Get the size of a partition extended header
/// </summary>
/// <returns>Size of the partition extended header in bytes, 0 on error</returns>
public static uint GetExtendedHeaderSize(NCCHHeader header)
=> header.ExtendedHeaderSizeInBytes;
/// <summary>
/// Get the size of a partition RomFS
/// </summary>

View File

@@ -150,12 +150,10 @@ namespace NDecrypt.N3DS
// Determine the Keys to be used
SetEncryptionKeys(cart, index, encrypt);
// Process the extended header
ProcessExtendedHeader(cart, index, encrypt, input, output);
// If we're encrypting, encrypt the filesystems and update the flags
if (encrypt)
{
EncryptExtendedHeader(cart, index, input, output);
EncryptExeFS(cart, index, input, output);
EncryptRomFS(cart, index, input, output);
UpdateEncryptCryptoAndMasks(cart, index, output);
@@ -164,6 +162,7 @@ namespace NDecrypt.N3DS
// If we're decrypting, decrypt the filesystems and update the flags
else
{
DecryptExtendedHeader(cart, index, input, output);
DecryptExeFS(cart, index, input, output);
DecryptRomFS(cart, index, input, output);
UpdateDecryptCryptoAndMasks(cart, index, output);
@@ -205,54 +204,54 @@ namespace NDecrypt.N3DS
KeysMap[index] = new PartitionKeys(_decryptArgs, rsaSignature, masks, method, _development);
}
/// <summary>
/// Process the extended header, if it exists
/// </summary>
/// <param name="cart">Cart representing the 3DS file</param>
/// <param name="index">Index of the partition</param>
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
/// <param name="input">Stream representing the input</param>
/// <param name="output">Stream representing the output</param>
private bool ProcessExtendedHeader(Cart cart, int index, bool encrypt, Stream input, Stream output)
{
// Get required offsets
uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
uint partitionOffset = partitionOffsetMU * cart.MediaUnitSize();
if (cart.Partitions![index]!.ExtendedHeaderSizeInBytes > 0)
{
// Seek to the extended header
input.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
output.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
Console.WriteLine($"Partition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
// Create the Plain AES cipher for this partition
var cipher = CreateAESCipher(KeysMap[index].NormalKey2C, cart.PlainIV(index), encrypt);
// Process the extended header
byte[] readBytes = input.ReadBytes(Constants.CXTExtendedDataHeaderLength);
byte[] processedBytes = cipher.ProcessBytes(readBytes);
output.Write(processedBytes);
#if NET6_0_OR_GREATER
// In .NET 6.0, this operation is not picked up by the reader, so we have to force it to reload its buffer
input.Seek(0, SeekOrigin.Begin);
#endif
output.Flush();
return true;
}
else
{
Console.WriteLine($"Partition {index} ExeFS: No Extended Header... Skipping...");
return false;
}
}
#endregion
#region Decrypt
/// <summary>
/// Decrypt the extended header, if it exists
/// </summary>
/// <param name="cart">Cart representing the 3DS file</param>
/// <param name="index">Index of the partition</param>
/// <param name="input">Stream representing the input</param>
/// <param name="output">Stream representing the output</param>
private bool DecryptExtendedHeader(Cart cart, int index, Stream input, Stream output)
{
// Get required offsets
uint partitionOffset = GetPartitionOffset(cart, index);
if (partitionOffset == 0)
{
Console.WriteLine($"Partition {index} ExeFS: No Data... Skipping...");
return false;
}
uint extHeaderSize = GetExtendedHeaderSize(cart, index);
if (extHeaderSize == 0)
{
Console.WriteLine($"Partition {index} RomFS: No Extended Header... Skipping...");
return false;
}
// Seek to the extended header
input.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
output.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
Console.WriteLine($"Partition {index} ExeFS: Decrypting: ExHeader");
// Create the Plain AES cipher for this partition
var cipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, cart.PlainIV(index));
// Process the extended header
PerformAESOperation(Constants.CXTExtendedDataHeaderLength, cipher, input, output, null);
#if NET6_0_OR_GREATER
// In .NET 6.0, this operation is not picked up by the reader, so we have to force it to reload its buffer
input.Seek(0, SeekOrigin.Begin);
#endif
output.Flush();
return true;
}
/// <summary>
/// Decrypt the ExeFS, if it exists
/// </summary>
@@ -398,7 +397,7 @@ namespace NDecrypt.N3DS
/// <param name="output">Stream representing the output</param>
private bool DecryptRomFS(Cart cart, int index, Stream input, Stream output)
{
// Get required offsets
// Validate the RomFS
uint romFsOffset = GetRomFSOffset(cart, index);
if (romFsOffset == 0)
{
@@ -406,6 +405,13 @@ namespace NDecrypt.N3DS
return false;
}
uint romFsSize = GetRomFSSize(cart, index);
if (romFsSize == 0)
{
Console.WriteLine($"Partition {index} RomFS: No Data... Skipping...");
return false;
}
// Seek to the RomFS
input.Seek(romFsOffset, SeekOrigin.Begin);
output.Seek(romFsOffset, SeekOrigin.Begin);
@@ -414,7 +420,6 @@ namespace NDecrypt.N3DS
var cipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey, cart.RomFSIV(index));
// Setup and perform the decryption
uint romFsSize = GetRomFSSize(cart, index);
PerformAESOperation(romFsSize,
cipher,
input,
@@ -457,6 +462,50 @@ namespace NDecrypt.N3DS
#region Encrypt
/// <summary>
/// Encrypt the extended header, if it exists
/// </summary>
/// <param name="cart">Cart representing the 3DS file</param>
/// <param name="index">Index of the partition</param>
/// <param name="input">Stream representing the input</param>
/// <param name="output">Stream representing the output</param>
private bool EncryptExtendedHeader(Cart cart, int index, Stream input, Stream output)
{
// Get required offsets
uint partitionOffset = GetPartitionOffset(cart, index);
if (partitionOffset == 0)
{
Console.WriteLine($"Partition {index} ExeFS: No Data... Skipping...");
return false;
}
uint extHeaderSize = GetExtendedHeaderSize(cart, index);
if (extHeaderSize == 0)
{
Console.WriteLine($"Partition {index} RomFS: No Extended Header... Skipping...");
return false;
}
// Seek to the extended header
input.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
output.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
Console.WriteLine($"Partition {index} ExeFS: Encrypting: ExHeader");
// Create the Plain AES cipher for this partition
var cipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, cart.PlainIV(index));
// Process the extended header
PerformAESOperation(Constants.CXTExtendedDataHeaderLength, cipher, input, output, null);
#if NET6_0_OR_GREATER
// In .NET 6.0, this operation is not picked up by the reader, so we have to force it to reload its buffer
input.Seek(0, SeekOrigin.Begin);
#endif
output.Flush();
return true;
}
/// <summary>
/// Encrypt the ExeFS, if it exists
/// </summary>
@@ -603,7 +652,7 @@ namespace NDecrypt.N3DS
/// <param name="output">Stream representing the output</param>
private bool EncryptRomFS(Cart cart, int index, Stream input, Stream output)
{
// Get required offset
// Validate the RomFS
uint romFsOffset = GetRomFSOffset(cart, index);
if (romFsOffset == 0)
{
@@ -611,6 +660,13 @@ namespace NDecrypt.N3DS
return false;
}
uint romFsSize = GetRomFSSize(cart, index);
if (romFsSize == 0)
{
Console.WriteLine($"Partition {index} RomFS: No Data... Skipping...");
return false;
}
// Seek to the RomFS
input.Seek(romFsOffset, SeekOrigin.Begin);
output.Seek(romFsOffset, SeekOrigin.Begin);
@@ -635,7 +691,6 @@ namespace NDecrypt.N3DS
var cipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey, cart.RomFSIV(index));
// Setup and perform the decryption
uint romFsSize = GetRomFSSize(cart, index);
PerformAESOperation(romFsSize,
cipher,
input,