Use fixed array structs instead of Data* structs

This commit is contained in:
Alex Barney 2021-12-29 10:06:02 -07:00
parent 53e5029ef4
commit 5013e7d2ec
9 changed files with 114 additions and 105 deletions

View File

@ -99,46 +99,46 @@ public static class KeysCodeGen
RSAParameters betaNca0Params = RSAParameters betaNca0Params =
Rsa.RecoverParameters(BetaNca0Modulus, StandardPublicExponent, BetaNca0Exponent); Rsa.RecoverParameters(BetaNca0Modulus, StandardPublicExponent, BetaNca0Exponent);
betaNca0Params.D.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.PrivateExponent.Data); betaNca0Params.D.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.PrivateExponent.Items);
betaNca0Params.DP.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.Dp.Data); betaNca0Params.DP.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.Dp.Items);
betaNca0Params.DQ.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.Dq.Data); betaNca0Params.DQ.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.Dq.Items);
betaNca0Params.Exponent.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.PublicExponent.Data); betaNca0Params.Exponent.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.PublicExponent.Items);
betaNca0Params.InverseQ.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.InverseQ.Data); betaNca0Params.InverseQ.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.InverseQ.Items);
betaNca0Params.Modulus.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.Modulus.Data); betaNca0Params.Modulus.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.Modulus.Items);
betaNca0Params.P.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.P.Data); betaNca0Params.P.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.P.Items);
betaNca0Params.Q.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.Q.Data); betaNca0Params.Q.AsSpan().CopyTo(keySet.BetaNca0KeyAreaKey.Q.Items);
// First populate the prod RSA keys // First populate the prod RSA keys
keySet.SetMode(KeySet.Mode.Prod); keySet.SetMode(KeySet.Mode.Prod);
StandardPublicExponent.CopyTo(keySet.NcaHeaderSigningKeys[0].PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.NcaHeaderSigningKeys[0].PublicExponent.Items);
StandardPublicExponent.CopyTo(keySet.NcaHeaderSigningKeys[1].PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.NcaHeaderSigningKeys[1].PublicExponent.Items);
NcaHdrFixedKeyModulus0Prod.CopyTo(keySet.NcaHeaderSigningKeys[0].Modulus.Data); NcaHdrFixedKeyModulus0Prod.CopyTo(keySet.NcaHeaderSigningKeys[0].Modulus.Items);
NcaHdrFixedKeyModulus1Prod.CopyTo(keySet.NcaHeaderSigningKeys[1].Modulus.Data); NcaHdrFixedKeyModulus1Prod.CopyTo(keySet.NcaHeaderSigningKeys[1].Modulus.Items);
StandardPublicExponent.CopyTo(keySet.AcidSigningKeys[0].PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.AcidSigningKeys[0].PublicExponent.Items);
StandardPublicExponent.CopyTo(keySet.AcidSigningKeys[1].PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.AcidSigningKeys[1].PublicExponent.Items);
AcidFixedKeyModulus0Prod.CopyTo(keySet.AcidSigningKeys[0].Modulus.Data); AcidFixedKeyModulus0Prod.CopyTo(keySet.AcidSigningKeys[0].Modulus.Items);
AcidFixedKeyModulus1Prod.CopyTo(keySet.AcidSigningKeys[1].Modulus.Data); AcidFixedKeyModulus1Prod.CopyTo(keySet.AcidSigningKeys[1].Modulus.Items);
StandardPublicExponent.CopyTo(keySet.Package2SigningKey.PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.Package2SigningKey.PublicExponent.Items);
Package2FixedKeyModulusProd.CopyTo(keySet.Package2SigningKey.Modulus.Data); Package2FixedKeyModulusProd.CopyTo(keySet.Package2SigningKey.Modulus.Items);
// Populate the dev RSA keys // Populate the dev RSA keys
keySet.SetMode(KeySet.Mode.Dev); keySet.SetMode(KeySet.Mode.Dev);
StandardPublicExponent.CopyTo(keySet.NcaHeaderSigningKeys[0].PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.NcaHeaderSigningKeys[0].PublicExponent.Items);
StandardPublicExponent.CopyTo(keySet.NcaHeaderSigningKeys[1].PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.NcaHeaderSigningKeys[1].PublicExponent.Items);
NcaHdrFixedKeyModulus0Dev.CopyTo(keySet.NcaHeaderSigningKeys[0].Modulus.Data); NcaHdrFixedKeyModulus0Dev.CopyTo(keySet.NcaHeaderSigningKeys[0].Modulus.Items);
NcaHdrFixedKeyModulus1Dev.CopyTo(keySet.NcaHeaderSigningKeys[1].Modulus.Data); NcaHdrFixedKeyModulus1Dev.CopyTo(keySet.NcaHeaderSigningKeys[1].Modulus.Items);
StandardPublicExponent.CopyTo(keySet.AcidSigningKeys[0].PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.AcidSigningKeys[0].PublicExponent.Items);
StandardPublicExponent.CopyTo(keySet.AcidSigningKeys[1].PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.AcidSigningKeys[1].PublicExponent.Items);
AcidFixedKeyModulus0Dev.CopyTo(keySet.AcidSigningKeys[0].Modulus.Data); AcidFixedKeyModulus0Dev.CopyTo(keySet.AcidSigningKeys[0].Modulus.Items);
AcidFixedKeyModulus1Dev.CopyTo(keySet.AcidSigningKeys[1].Modulus.Data); AcidFixedKeyModulus1Dev.CopyTo(keySet.AcidSigningKeys[1].Modulus.Items);
StandardPublicExponent.CopyTo(keySet.Package2SigningKey.PublicExponent.Data); StandardPublicExponent.CopyTo(keySet.Package2SigningKey.PublicExponent.Items);
Package2FixedKeyModulusDev.CopyTo(keySet.Package2SigningKey.Modulus.Data); Package2FixedKeyModulusDev.CopyTo(keySet.Package2SigningKey.Modulus.Items);
return keySet; return keySet;
} }

View File

@ -225,8 +225,8 @@ public class KeySet
{ {
return new RSAParameters return new RSAParameters
{ {
Exponent = key.PublicExponent.DataRo.ToArray(), Exponent = key.PublicExponent.ItemsRo.ToArray(),
Modulus = key.Modulus.DataRo.ToArray() Modulus = key.Modulus.ItemsRo.ToArray()
}; };
} }
@ -234,14 +234,14 @@ public class KeySet
{ {
return new RSAParameters return new RSAParameters
{ {
D = key.PrivateExponent.DataRo.ToArray(), D = key.PrivateExponent.ItemsRo.ToArray(),
DP = key.Dp.DataRo.ToArray(), DP = key.Dp.ItemsRo.ToArray(),
DQ = key.Dq.DataRo.ToArray(), DQ = key.Dq.ItemsRo.ToArray(),
Exponent = key.PublicExponent.DataRo.ToArray(), Exponent = key.PublicExponent.ItemsRo.ToArray(),
InverseQ = key.InverseQ.DataRo.ToArray(), InverseQ = key.InverseQ.ItemsRo.ToArray(),
Modulus = key.Modulus.DataRo.ToArray(), Modulus = key.Modulus.ItemsRo.ToArray(),
P = key.P.DataRo.ToArray(), P = key.P.ItemsRo.ToArray(),
Q = key.Q.DataRo.ToArray() Q = key.Q.ItemsRo.ToArray()
}; };
} }

View File

@ -3,6 +3,7 @@ using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using LibHac.Common; using LibHac.Common;
using LibHac.Common.FixedArrays;
using LibHac.Util; using LibHac.Util;
namespace LibHac.Crypto; namespace LibHac.Crypto;
@ -117,49 +118,21 @@ public struct AesCmac
#endif #endif
} }
[StructLayout(LayoutKind.Sequential)]
public struct RsaFullKey public struct RsaFullKey
{ {
public Data100 PrivateExponent; // ReSharper disable once UnassignedField.Global
public Data80 Dp; public Array256<byte> PrivateExponent;
public Data80 Dq; public Array128<byte> Dp;
public Data3 PublicExponent; public Array128<byte> Dq;
public Data80 InverseQ; public Array3<byte> PublicExponent;
public Data100 Modulus; public Array128<byte> InverseQ;
public Data80 P; public Array256<byte> Modulus;
public Data80 Q; public Array128<byte> P;
public Array128<byte> Q;
} }
[StructLayout(LayoutKind.Sequential)]
public struct RsaKey public struct RsaKey
{ {
public Data100 Modulus; public Array256<byte> Modulus;
public Data3 PublicExponent; public Array3<byte> PublicExponent;
}
[StructLayout(LayoutKind.Explicit, Size = 0x100)]
public struct Data100
{
[FieldOffset(0)] private byte _byte;
public Span<byte> Data => SpanHelpers.CreateSpan(ref _byte, 0x100);
public readonly ReadOnlySpan<byte> DataRo => SpanHelpers.CreateReadOnlySpan(in _byte, 0x100);
}
[StructLayout(LayoutKind.Explicit, Size = 0x80)]
public struct Data80
{
[FieldOffset(0)] private byte _byte;
public Span<byte> Data => SpanHelpers.CreateSpan(ref _byte, 0x80);
public readonly ReadOnlySpan<byte> DataRo => SpanHelpers.CreateReadOnlySpan(in _byte, 0x80);
}
[StructLayout(LayoutKind.Explicit, Size = 3)]
public struct Data3
{
[FieldOffset(0)] private byte _byte;
public Span<byte> Data => SpanHelpers.CreateSpan(ref _byte, 3);
public readonly ReadOnlySpan<byte> DataRo => SpanHelpers.CreateReadOnlySpan(in _byte, 3);
} }

View File

@ -1,18 +1,12 @@
using System.Runtime.InteropServices; using LibHac.Common.FixedArrays;
using LibHac.Common;
namespace LibHac.Fat; namespace LibHac.Fat;
[StructLayout(LayoutKind.Explicit, Size = 0x20)]
public struct FatError public struct FatError
{ {
private const int FunctionNameLength = 0x10; public int Error;
public int ExtraError;
[FieldOffset(0x00)] public int Error; public int DriveId;
[FieldOffset(0x04)] public int ExtraError; public Array16<byte> ErrorName;
[FieldOffset(0x08)] public int DriveId; public int Reserved;
[FieldOffset(0x0C)] private byte _functionName;
public U8SpanMutable ErrorName =>
new U8SpanMutable(SpanHelpers.CreateSpan(ref _functionName, FunctionNameLength));
} }

View File

@ -11,7 +11,7 @@ namespace LibHac.Fs.Fsa;
public static class MountUtility public static class MountUtility
{ {
internal static Result GetMountNameAndSubPath(out MountName mountName, out U8Span subPath, U8Span path) private static Result GetMountNameAndSubPath(out MountName mountName, out U8Span subPath, U8Span path)
{ {
UnsafeHelpers.SkipParamInit(out mountName); UnsafeHelpers.SkipParamInit(out mountName);
subPath = default; subPath = default;

View File

@ -1,15 +1,15 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices;
using LibHac.Common; using LibHac.Common;
using LibHac.Common.FixedArrays;
namespace LibHac.Fs; namespace LibHac.Fs;
[StructLayout(LayoutKind.Sequential, Size = 16)]
[DebuggerDisplay("{ToString()}")] [DebuggerDisplay("{ToString()}")]
internal struct MountName internal struct MountName
{ {
public Span<byte> Name => SpanHelpers.AsByteSpan(ref this); private Array16<byte> _nameArray;
public Span<byte> Name => _nameArray.Items;
public override string ToString() => new U8Span(Name).ToString(); public override string ToString() => new U8Span(Name).ToString();
} }

View File

@ -1,19 +1,19 @@
using System; using System;
using LibHac.Crypto; using LibHac.Common.FixedArrays;
namespace LibHac.FsSrv; namespace LibHac.FsSrv;
public class SaveDataTransferCryptoConfiguration public class SaveDataTransferCryptoConfiguration
{ {
private Data100 _tokenSigningKeyModulus; private Array256<byte> _tokenSigningKeyModulus;
private Data100 _keySeedPackageSigningKeyModulus; private Array256<byte> _keySeedPackageSigningKeyModulus;
private Data100 _kekEncryptionKeyModulus; private Array256<byte> _kekEncryptionKeyModulus;
private Data100 _keyPackageSigningModulus; private Array256<byte> _keyPackageSigningModulus;
public Span<byte> TokenSigningKeyModulus => _tokenSigningKeyModulus.Data; public Span<byte> TokenSigningKeyModulus => _tokenSigningKeyModulus.Items;
public Span<byte> KeySeedPackageSigningKeyModulus => _keySeedPackageSigningKeyModulus.Data; public Span<byte> KeySeedPackageSigningKeyModulus => _keySeedPackageSigningKeyModulus.Items;
public Span<byte> KekEncryptionKeyModulus => _kekEncryptionKeyModulus.Data; public Span<byte> KekEncryptionKeyModulus => _kekEncryptionKeyModulus.Items;
public Span<byte> KeyPackageSigningModulus => _keyPackageSigningModulus.Data; public Span<byte> KeyPackageSigningModulus => _keyPackageSigningModulus.Items;
public SaveTransferAesKeyGenerator GenerateAesKey { get; set; } public SaveTransferAesKeyGenerator GenerateAesKey { get; set; }
public RandomDataGenerator GenerateRandomData { get; set; } public RandomDataGenerator GenerateRandomData { get; set; }

View File

@ -0,0 +1,19 @@
using System;
using System.Runtime.CompilerServices;
namespace LibHac.Tests.Common;
public class Layout
{
public static int GetOffset<TStruct, TField>(in TStruct structRef, in TField fieldRef)
{
ref TField structOffset = ref Unsafe.As<TStruct, TField>(ref Unsafe.AsRef(in structRef));
ref TField fieldOffset = ref Unsafe.AsRef(in fieldRef);
int offset = Unsafe.ByteOffset(ref structOffset, ref fieldOffset).ToInt32();
if (offset >= Unsafe.SizeOf<TStruct>())
throw new ArgumentException($"Error getting field offset. {nameof(structRef)} and {nameof(fieldRef)} must be from the same struct instance.");
return offset;
}
}

View File

@ -0,0 +1,23 @@
using System.Runtime.CompilerServices;
using LibHac.Fat;
using Xunit;
using static LibHac.Tests.Common.Layout;
namespace LibHac.Tests.Fat;
public class TypeLayoutTests
{
[Fact]
public static void FatError_Layout()
{
var s = new FatError();
Assert.Equal(0x20, Unsafe.SizeOf<FatError>());
Assert.Equal(0x00, GetOffset(in s, in s.Error));
Assert.Equal(0x04, GetOffset(in s, in s.ExtraError));
Assert.Equal(0x08, GetOffset(in s, in s.DriveId));
Assert.Equal(0x0C, GetOffset(in s, in s.ErrorName));
Assert.Equal(0x1C, GetOffset(in s, in s.Reserved));
}
}