Add GetAsicCertificate

This commit is contained in:
Alex Barney 2023-10-30 23:54:13 -07:00
parent e49523eed6
commit 283ecf81ff
8 changed files with 110 additions and 8 deletions

View file

@ -50,6 +50,7 @@ namespace LibHac.Common.FixedArrays;
[InlineArray(640)] public struct Array640<T> { public readonly int Length => 640; private T _0; }
[InlineArray(768)] public struct Array768<T> { public readonly int Length => 768; private T _0; }
[InlineArray(769)] public struct Array769<T> { public readonly int Length => 769; private T _0; }
[InlineArray(1024)] public struct Array1024<T> { public readonly int Length => 1024; private T _0; }
[InlineArray(3000)] public struct Array3000<T> { public readonly int Length => 3000; private T _0; }
[InlineArray(3438)] public struct Array3438<T> { public readonly int Length => 3438; private T _0; }
[InlineArray(5366)] public struct Array5366<T> { public readonly int Length => 5366; private T _0; }

View file

@ -428,4 +428,12 @@ public sealed class GameCardEmulated : IGcApi
outErrorReportInfo = default;
return Result.Success;
}
public Result GetAsicCertificate(out GameCardAsicCertificateSet outCertificateSet)
{
Abort.DoAbortUnless(_initialized, LibNotInitializedMessage);
outCertificateSet = default;
return Result.Success;
}
}

View file

@ -30,4 +30,12 @@ public struct GameCardIdSet
public CardId1 Id1;
public CardId2 Id2;
public CardId3 Id3;
}
public struct GameCardAsicCertificateSet
{
public Array1024<byte> Certificate;
public Array16<byte> SerialNumber;
public Array256<byte> PublicKeyModulus;
public Array3<byte> PublicKeyExponent;
}

View file

@ -5,17 +5,61 @@ namespace LibHac.Gc;
public static class Values
{
public const int GcPageSize = 0x200;
public const int GcAsicFirmwareSize = 1024 * 30; // 30 KiB
public const int GcCardDeviceIdSize = 0x10;
public const int GcChallengeCardExistenceResponseSize = 0x58;
public const int GcCardImageHashSize = 0x20;
public const int GcDeviceCertificateSize = 0x200;
public const int GcCardKeyAreaSize = GcCardKeyAreaPageCount * GcPageSize;
public const int GcCardKeyAreaPageCount = 8;
public const int GcCertAreaPageAddress = 56;
public const int GcCardKeyAreaSize = GcCardKeyAreaPageCount * GcPageSize;
public const int GcCardHeaderPageAddress = 0;
public const int GcCardHeaderPageCount = 1;
public const int GcReservedAreaPageCount = 0x37;
public const int GcCertAreaPageAddress = GcCardHeaderPageCount + GcReservedAreaPageCount;
public const int GcDeviceCertificatePageCount = 1;
public const int GcCertAreaPageCount = 0x40;
public const int GcPackageIdSize = 8;
public const int GcPartitionFsHeaderHashSize = 0x20;
public const int GcCardDeviceIdSize = 0x10;
public const int GcDeviceCertificateSize = 0x200;
public const int GcCardImageHashSize = 0x20;
public const int GcChallengeCardExistenceResponseSize = 0x58;
public const int GcChallengeCardExistenceSeedSize = 0xF;
public const int GcChallengeCardExistenceValueSize = 0x10;
public const int GcMmcCmd60DataSize = 0x40;
public const int GcAsicFirmwareSize = 1024 * 30; // 30 KiB
public const int GcAsicSerialNumberLength = 0x10;
public const int GcRandomValueSize = 32;
public const int GcRandomValueForKeyUpdateSocSize = 31;
public const int GcRsaOaepSeedSize = 32;
public const int GcAesBlockLength = Aes.BlockSize;
public const int GcRsaKeyLength = Rsa.ModulusSize2048Pss;
public const int GcRsaPublicExponentLength = Rsa.MaximumExponentSize2048Pss;
public const int GcAesKeyLength = Aes.KeySize128;
public const int GcAesCbcIvLength = Aes.KeySize128;
public const int GcHmacKeyLength = 0x20;
public const int GcCvConstLength = 0x10;
public const int GcTitleKeyKekIndexMax = 0x10;
public const int GcSha256HashLength = Sha256.DigestSize;
public const int GcSendCommandMaxCount = 3;
public const byte GcPaddingU8 = 0xFF;
public const int GcCertificateSize = 0x400;
public const int GcSocModulusOffset = 0x130;
public const int GcCertificateSetSize = GcCertificateSize + GcAsicSerialNumberLength + GcRsaKeyLength + GcRsaPublicExponentLength;
public const long UnusedAreaSizeBase = 1024 * 1024 * 72; // 72 MiB
public const long MemorySizeBase = 1024 * 1024 * 1024; // 1 GiB
public const long AvailableSizeBase = MemorySizeBase - UnusedAreaSizeBase;
public const int Cmd60DefaultTimeOutMilliSeconds = 3500;
public const int EraseTimeOutMilliSeconds = 10 * 1000;
}

View file

@ -35,4 +35,5 @@ public interface IGcApi
void UnregisterDetectionEventCallback();
Result GetCardHeader(Span<byte> destBuffer);
Result GetErrorInfo(out GameCardErrorReportInfo outErrorReportInfo);
Result GetAsicCertificate(out GameCardAsicCertificateSet outCertificateSet);
}

View file

@ -768,6 +768,17 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
bytesWritten = Unsafe.SizeOf<DevCardParameter>();
return Result.Success;
}
case GameCardManagerOperationIdValue.GetGameCardAsicCertificate:
{
if (buffer.Size < Unsafe.SizeOf<GameCardAsicCertificateSet>())
return ResultFs.InvalidArgument.Log();
res = GetGameCardAsicCertificate(out buffer.As<GameCardAsicCertificateSet>());
if (res.IsFailure()) return res.Miss();
bytesWritten = Unsafe.SizeOf<GameCardAsicCertificateSet>();
return Result.Success;
}
default:
return ResultFs.InvalidArgument.Log();
@ -1042,6 +1053,16 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
return Result.Success;
}
private Result GetGameCardAsicCertificate(out GameCardAsicCertificateSet outCertificateSet)
{
UnsafeHelpers.SkipParamInit(out outCertificateSet);
Result res = InitializeGcLibrary();
if (res.IsFailure()) return res.Miss();
return _gc.GetAsicCertificate(out outCertificateSet).Ret();
}
public Result AcquireReadLock(ref SharedLock<ReaderWriterLock> outLock, GameCardHandle handle)
{
using (var readLock = new SharedLock<ReaderWriterLock>(_rwLock))

View file

@ -19,7 +19,8 @@ public enum GameCardManagerOperationIdValue
ReadParamDirectly = 11,
WriteToGameCardDirectly = 12,
ForceErase = 13,
SimulateDetectionEventSignaled = 14
SimulateDetectionEventSignaled = 14,
GetGameCardAsicCertificate = 15
}
/// <summary>

View file

@ -87,6 +87,24 @@ public class TypeLayoutTests
Assert.Equal(0, GetOffset(in s, in s.Reserved));
}
[Fact]
public static void GameCardAsicCertificateSet_Layout()
{
var s = new GameCardAsicCertificateSet();
Assert.Equal(Values.GcCertificateSetSize, Unsafe.SizeOf<GameCardAsicCertificateSet>());
Assert.Equal(0x000, GetOffset(in s, in s.Certificate));
Assert.Equal(0x400, GetOffset(in s, in s.SerialNumber));
Assert.Equal(0x410, GetOffset(in s, in s.PublicKeyModulus));
Assert.Equal(0x510, GetOffset(in s, in s.PublicKeyExponent));
Assert.Equal(Values.GcCertificateSize, s.Certificate.Length);
Assert.Equal(Values.GcAsicSerialNumberLength, s.SerialNumber.Length);
Assert.Equal(Values.GcRsaKeyLength, s.PublicKeyModulus.Length);
Assert.Equal(Values.GcRsaPublicExponentLength, s.PublicKeyExponent.Length);
}
[Fact]
public static void CardInitialDataPayload_Layout()
{