diff --git a/build/CodeGen/results.csv b/build/CodeGen/results.csv index ef973e5e..f9c257ec 100644 --- a/build/CodeGen/results.csv +++ b/build/CodeGen/results.csv @@ -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, \ No newline at end of file diff --git a/src/LibHac/Boot/Package1.cs b/src/LibHac/Boot/Package1.cs index 58199121..3dab974e 100644 --- a/src/LibHac/Boot/Package1.cs +++ b/src/LibHac/Boot/Package1.cs @@ -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; } + /// + /// Calculates the MAC for a modern Erista pk11. + /// + /// The buffer where the generated MAC will be placed. Must be at least 16 bytes long. + /// : The operation was successful.
+ /// : The package1 type does not support calculating + /// a MAC over its pk11.
+ /// : The key used to calculate the MAC was not found + /// in the .
+ public Result CalculateModernEristaMac(Span 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; + } + /// /// Read the encrypted section of a Mariko Package1 and try to decrypt it. /// @@ -336,7 +367,7 @@ public class Package1 Assert.SdkRequires(IsDecrypted); int pk11Size = Unsafe.SizeOf() + GetSectionSize(Package1Section.WarmBoot) + - GetSectionSize(Package1Section.Bootloader) + GetSectionSize(Package1Section.SecureMonitor); + GetSectionSize(Package1Section.Bootloader) + GetSectionSize(Package1Section.SecureMonitor); pk11Size = Alignment.AlignUp(pk11Size, 0x10); diff --git a/src/LibHac/Common/Keys/KeyDerivation.cs b/src/LibHac/Common/Keys/KeyDerivation.cs index b7a017eb..10556fc2 100644 --- a/src/LibHac/Common/Keys/KeyDerivation.cs +++ b/src/LibHac/Common/Keys/KeyDerivation.cs @@ -89,7 +89,7 @@ internal static class KeyDerivation Encryption, Signature, Kek, - + // TSEC directly uses the value generated by this (no key derivation) to encrypt pk11's AES IV that's found // at 0x6FF0 in package1. When decrypting pk11, TSEC will overwrite the unencrypted IV in package1 with the // encrypted IV. diff --git a/src/LibHac/Common/ResultLibHac.cs b/src/LibHac/Common/ResultLibHac.cs index 78b1e71d..e8d388ad 100644 --- a/src/LibHac/Common/ResultLibHac.cs +++ b/src/LibHac/Common/ResultLibHac.cs @@ -92,4 +92,16 @@ public static class ResultLibHac public static Result.Base InvalidPackage1MarikoBodySize => new Result.Base(ModuleLibHac, 1042); /// Error code: 2428-1043; Inner value: 0x827ac public static Result.Base InvalidPackage1Pk11Size => new Result.Base(ModuleLibHac, 1043); + + /// Error code: 2428-2000; Range: 2000-2199; Inner value: 0xfa1ac + public static Result.Base PreconditionViolation { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleLibHac, 2000, 2199); } + /// Error code: 2428-2001; Range: 2001-2019; Inner value: 0xfa3ac + public static Result.Base UnsupportedOperation { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleLibHac, 2001, 2019); } + /// The package1 type doesn't support calculating a MAC over its pk11. Only modern Erista package1s support this.
Error code: 2428-2002; Inner value: 0xfa5ac
+ public static Result.Base UnsupportedCalculateMacForPackage1 => new Result.Base(ModuleLibHac, 2002); + + /// Error code: 2428-2050; Range: 2050-2069; Inner value: 0x1005ac + public static Result.Base KeyNotFound { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleLibHac, 2050, 2069); } + /// Error code: 2428-2051; Inner value: 0x1007ac + public static Result.Base Package1MacKeyNotFound => new Result.Base(ModuleLibHac, 2051); } \ No newline at end of file diff --git a/src/hactoolnet/ProcessPackage.cs b/src/hactoolnet/ProcessPackage.cs index ca614a67..b39c70a3 100644 --- a/src/hactoolnet/ProcessPackage.cs +++ b/src/hactoolnet/ProcessPackage.cs @@ -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 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}");