Add a function to calculate a pk11 mac and use it in hactoolnet

This commit is contained in:
Alex Barney 2023-01-30 19:26:37 -07:00
parent bb13864030
commit a1439a2647
5 changed files with 71 additions and 5 deletions

View file

@ -1935,3 +1935,10 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
428,1041,,,,InvalidPackage1SectionSize,
428,1042,,,,InvalidPackage1MarikoBodySize,
428,1043,,,,InvalidPackage1Pk11Size,
428,2000,2199,,,PreconditionViolation,
428,2001,2019,,,UnsupportedOperation,
428,2002,,,,UnsupportedCalculateMacForPackage1,The package1 type doesn't support calculating a MAC over its pk11. Only modern Erista package1s support this.
428,2050,2069,,,KeyNotFound,
428,2051,,,,Package1MacKeyNotFound,
1 Module DescriptionStart DescriptionEnd Flags Namespace Name Summary
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944

View file

@ -6,10 +6,12 @@ using System.Runtime.InteropServices;
using LibHac.Common;
using LibHac.Common.FixedArrays;
using LibHac.Common.Keys;
using LibHac.Crypto;
using LibHac.Diag;
using LibHac.Fs;
using LibHac.Tools.FsSystem;
using LibHac.Util;
using AesKey = LibHac.Crypto.AesKey;
namespace LibHac.Boot;
@ -153,6 +155,35 @@ public class Package1
return Result.Success;
}
/// <summary>
/// Calculates the MAC for a modern Erista pk11.
/// </summary>
/// <param name="macBuffer">The buffer where the generated MAC will be placed. Must be at least 16 bytes long.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultLibHac.UnsupportedCalculateMacForPackage1"/>: The package1 type does not support calculating
/// a MAC over its pk11.<br/>
/// <see cref="ResultLibHac.Package1MacKeyNotFound"/>: The key used to calculate the MAC was not found
/// in the <see cref="KeySet"/>.</returns>
public Result CalculateModernEristaMac(Span<byte> macBuffer)
{
if (IsMariko || !IsModern)
return ResultLibHac.UnsupportedCalculateMacForPackage1.Log();
AesKey macKey = KeySet.Package1MacKeys[KeyRevision];
if (macKey.IsZeros())
return ResultLibHac.Package1MacKeyNotFound.Log();
// Todo: Use a smaller buffer instead of reading the entire thing in at once.
byte[] macTarget = new byte[Pk11Size + 0x20];
Result res = _bodyStorage.Read(0x7000 - 0x20, macTarget);
if (res.IsFailure()) return res.Miss();
Aes.CalculateCmac(macBuffer, macTarget, macKey);
return Result.Success;
}
/// <summary>
/// Read the encrypted section of a Mariko Package1 and try to decrypt it.
/// </summary>
@ -336,7 +367,7 @@ public class Package1
Assert.SdkRequires(IsDecrypted);
int pk11Size = Unsafe.SizeOf<Package1Pk11Header>() + GetSectionSize(Package1Section.WarmBoot) +
GetSectionSize(Package1Section.Bootloader) + GetSectionSize(Package1Section.SecureMonitor);
GetSectionSize(Package1Section.Bootloader) + GetSectionSize(Package1Section.SecureMonitor);
pk11Size = Alignment.AlignUp(pk11Size, 0x10);

View file

@ -92,4 +92,16 @@ public static class ResultLibHac
public static Result.Base InvalidPackage1MarikoBodySize => new Result.Base(ModuleLibHac, 1042);
/// <summary>Error code: 2428-1043; Inner value: 0x827ac</summary>
public static Result.Base InvalidPackage1Pk11Size => new Result.Base(ModuleLibHac, 1043);
/// <summary>Error code: 2428-2000; Range: 2000-2199; Inner value: 0xfa1ac</summary>
public static Result.Base PreconditionViolation { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleLibHac, 2000, 2199); }
/// <summary>Error code: 2428-2001; Range: 2001-2019; Inner value: 0xfa3ac</summary>
public static Result.Base UnsupportedOperation { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleLibHac, 2001, 2019); }
/// <summary>The package1 type doesn't support calculating a MAC over its pk11. Only modern Erista package1s support this.<br/>Error code: 2428-2002; Inner value: 0xfa5ac</summary>
public static Result.Base UnsupportedCalculateMacForPackage1 => new Result.Base(ModuleLibHac, 2002);
/// <summary>Error code: 2428-2050; Range: 2050-2069; Inner value: 0x1005ac</summary>
public static Result.Base KeyNotFound { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleLibHac, 2050, 2069); }
/// <summary>Error code: 2428-2051; Inner value: 0x1007ac</summary>
public static Result.Base Package1MacKeyNotFound => new Result.Base(ModuleLibHac, 2051);
}

View file

@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using LibHac;
@ -82,7 +83,22 @@ internal static class ProcessPackage
if (!package1.IsMariko && package1.IsModern)
{
PrintItem(sb, colLen, " PK11 MAC:", package1.Pk11Mac.ItemsRo.ToArray());
string validity = "";
Span<byte> mac = stackalloc byte[0x10];
Result res = package1.CalculateModernEristaMac(mac);
if (res.IsFailure())
{
if (!ResultLibHac.Package1MacKeyNotFound.Includes(res))
res.ThrowIfFailure();
}
else
{
validity = mac.SequenceEqual(package1.Pk11Mac) ? " (Valid)" : " (Invalid)";
}
PrintItem(sb, colLen, $" PK11 MAC:{validity}", package1.Pk11Mac.ItemsRo.ToArray());
}
if (package1.IsDecrypted)
@ -91,7 +107,7 @@ internal static class ProcessPackage
if (!package1.IsMariko)
{
PrintItem(sb, colLen, " Key Revision:", $"{package1.KeyRevision:x2} ({Utilities.GetKeyRevisionSummary(package1.KeyRevision)})");
PrintItem(sb, colLen, " Key Revision:", $"{package1.KeyRevision:x2}");
}
PrintItem(sb, colLen, " PK11 Size:", $"{package1.Pk11Size:x8}");