Rename IsEmpty to IsZeros

Renames the IsEmpty() functions that check if an array is all zeros. This helps avoid confusion because Span has an IsEmpty property that returns true if the span's length is 0.

The change actually revealed a tiny bug in KeyDerivation where the property was accidentally used instead of the function.
This commit is contained in:
Alex Barney 2020-10-11 23:47:26 -07:00
parent c39895080b
commit b6499a6c12
12 changed files with 59 additions and 59 deletions

View file

@ -61,7 +61,7 @@ namespace LibHacBuild.CodeGen.Stage2
sb.AppendSpacerLine();
sb.Append($"private static ReadOnlySpan<byte> {name} => new byte[]");
if (data.IsEmpty())
if (data.IsZeros())
{
sb.AppendLine(" { };");
return;

View file

@ -30,7 +30,7 @@ namespace LibHac.Boot
public readonly ReadOnlySpan<byte> ReadOnlyBytes => SpanHelpers.AsReadOnlyByteSpan(in this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool IsEmpty()
public readonly bool IsZeros()
{
ReadOnlySpan<ulong> ulongSpan = MemoryMarshal.Cast<byte, ulong>(ReadOnlyBytes);
@ -70,7 +70,7 @@ namespace LibHac.Boot
public readonly ReadOnlySpan<byte> ReadOnlyBytes => SpanHelpers.AsReadOnlyByteSpan(in this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool IsEmpty()
public readonly bool IsZeros()
{
ReadOnlySpan<ulong> ulongSpan = MemoryMarshal.Cast<byte, ulong>(ReadOnlyBytes);

View file

@ -354,7 +354,7 @@ namespace LibHac.Boot
// MarikoOemHeader must be read first
private bool IsMarikoImpl()
{
return MarikoOemHeader.AesMac.IsEmpty() && MarikoOemHeader.Reserved.IsEmpty();
return MarikoOemHeader.AesMac.IsZeros() && MarikoOemHeader.Reserved.IsZeros();
}
/// <summary>

View file

@ -56,7 +56,7 @@ namespace LibHac.Common.Keys
if (info.RangeType == RangeType.Single)
{
Span<byte> key = info.Getter(keySet, 0);
if (key.IsEmpty())
if (key.IsZeros())
continue;
if (isNewGroup)
@ -78,7 +78,7 @@ namespace LibHac.Common.Keys
for (int i = info.RangeStart; i < info.RangeEnd; i++)
{
Span<byte> key = info.Getter(keySet, i);
if (key.IsEmpty())
if (key.IsZeros())
continue;
if (hasPrintedKey == false)

View file

@ -26,14 +26,14 @@ namespace LibHac.Common.Keys
private static void DeriveKeyBlobKeys(KeySet s)
{
if (s.SecureBootKey.IsEmpty() || s.TsecKey.IsEmpty()) return;
if (s.SecureBootKey.IsZeros() || s.TsecKey.IsZeros()) return;
bool haveKeyBlobMacKeySource = !s.MasterKeySource.IsEmpty();
bool haveKeyBlobMacKeySource = !s.MasterKeySource.IsZeros();
var temp = new AesKey();
for (int i = 0; i < KeySet.UsedKeyBlobCount; i++)
{
if (s.KeyBlobKeySources[i].IsEmpty()) continue;
if (s.KeyBlobKeySources[i].IsZeros()) continue;
Aes.DecryptEcb128(s.KeyBlobKeySources[i], temp, s.TsecKey);
Aes.DecryptEcb128(temp, s.KeyBlobKeys[i], s.SecureBootKey);
@ -50,7 +50,7 @@ namespace LibHac.Common.Keys
for (int i = 0; i < KeySet.UsedKeyBlobCount; i++)
{
if (s.KeyBlobKeys[i].IsEmpty() || s.KeyBlobMacKeys[i].IsEmpty() || s.EncryptedKeyBlobs[i].IsEmpty())
if (s.KeyBlobKeys[i].IsZeros() || s.KeyBlobMacKeys[i].IsZeros() || s.EncryptedKeyBlobs[i].IsZeros())
{
continue;
}
@ -71,7 +71,7 @@ namespace LibHac.Common.Keys
{
for (int i = 0; i < KeySet.UsedKeyBlobCount; i++)
{
if (s.KeyBlobs[i].IsEmpty()) continue;
if (s.KeyBlobs[i].IsZeros()) continue;
s.MasterKeks[i] = s.KeyBlobs[i].MasterKek;
s.Package1Keys[i] = s.KeyBlobs[i].Package1Key;
@ -80,13 +80,13 @@ namespace LibHac.Common.Keys
private static void Derive620Keys(KeySet s)
{
bool haveTsecRootKek = !s.TsecRootKek.IsEmpty();
bool havePackage1MacKek = !s.Package1MacKek.IsEmpty();
bool havePackage1Kek = !s.Package1Kek.IsEmpty();
bool haveTsecRootKek = !s.TsecRootKek.IsZeros();
bool havePackage1MacKek = !s.Package1MacKek.IsZeros();
bool havePackage1Kek = !s.Package1Kek.IsZeros();
for (int i = KeySet.UsedKeyBlobCount; i < KeySet.KeyRevisionCount; i++)
{
if (s.TsecAuthSignatures[i - KeySet.UsedKeyBlobCount].IsEmpty())
if (s.TsecAuthSignatures[i - KeySet.UsedKeyBlobCount].IsZeros())
continue;
if (haveTsecRootKek)
@ -114,7 +114,7 @@ namespace LibHac.Common.Keys
{
// Key revisions >= 8 all use the same TSEC root key
int tsecRootKeyIndex = Math.Min(i, 8) - KeySet.UsedKeyBlobCount;
if (s.TsecRootKeys[tsecRootKeyIndex].IsEmpty() || s.MasterKekSources[i].IsEmpty()) continue;
if (s.TsecRootKeys[tsecRootKeyIndex].IsZeros() || s.MasterKekSources[i].IsZeros()) continue;
Aes.DecryptEcb128(s.MasterKekSources[i], s.MasterKeks[i], s.TsecRootKeys[tsecRootKeyIndex]);
}
@ -122,11 +122,11 @@ namespace LibHac.Common.Keys
private static void DeriveMarikoMasterKeks(KeySet s)
{
if (s.MarikoKek.IsEmpty()) return;
if (s.MarikoKek.IsZeros()) return;
for (int i = 0; i < KeySet.KeyRevisionCount; i++)
{
if (s.MarikoMasterKekSources[i].IsEmpty()) continue;
if (s.MarikoMasterKekSources[i].IsZeros()) continue;
Aes.DecryptEcb128(s.MarikoMasterKekSources[i], s.MasterKeks[i], s.MarikoKek);
}
@ -134,11 +134,11 @@ namespace LibHac.Common.Keys
private static void DeriveMasterKeys(KeySet s)
{
if (s.MasterKeySource.IsEmpty()) return;
if (s.MasterKeySource.IsZeros()) return;
for (int i = 0; i < KeySet.KeyRevisionCount; i++)
{
if (s.MasterKeks[i].IsEmpty()) continue;
if (s.MasterKeks[i].IsZeros()) continue;
Aes.DecryptEcb128(s.MasterKeySource, s.MasterKeys[i], s.MasterKeks[i]);
}
@ -153,7 +153,7 @@ namespace LibHac.Common.Keys
for (int i = keyVectors.Length - 1; i >= 0; i--)
{
if (!s.MasterKeys[i].IsEmpty())
if (!s.MasterKeys[i].IsZeros())
{
newestMasterKey = i;
break;
@ -196,7 +196,7 @@ namespace LibHac.Common.Keys
Aes.DecryptEcb128(keyVectors[0], key, key);
// If we don't get zeros, MasterKeys[generation] is incorrect
return key.IsEmpty();
return key.IsZeros();
}
private static ReadOnlySpan<AesKey> MasterKeyVectors(KeySet s) =>
@ -240,7 +240,7 @@ namespace LibHac.Common.Keys
var kek = new AesKey();
// Derive the device key
if (!s.PerConsoleKeySource.IsEmpty() && !s.KeyBlobKeys[0].IsEmpty())
if (!s.PerConsoleKeySource.IsZeros() && !s.KeyBlobKeys[0].IsZeros())
{
Aes.DecryptEcb128(s.PerConsoleKeySource, s.DeviceKey, s.KeyBlobKeys[0]);
}
@ -248,8 +248,8 @@ namespace LibHac.Common.Keys
// Derive device-unique save keys
for (int i = 0; i < s.DeviceUniqueSaveMacKeySources.Length; i++)
{
if (!s.DeviceUniqueSaveMacKekSource.IsEmpty() && !s.DeviceUniqueSaveMacKeySources[i].IsEmpty() &&
!s.DeviceKey.IsEmpty())
if (!s.DeviceUniqueSaveMacKekSource.IsZeros() && !s.DeviceUniqueSaveMacKeySources[i].IsZeros() &&
!s.DeviceKey.IsZeros())
{
GenerateKek(s.DeviceKey, s.DeviceUniqueSaveMacKekSource, kek, s.AesKekGenerationSource, null);
Aes.DecryptEcb128(s.DeviceUniqueSaveMacKeySources[i], s.DeviceUniqueSaveMacKeys[i], kek);
@ -257,44 +257,44 @@ namespace LibHac.Common.Keys
}
// Derive BIS keys
if (s.DeviceKey.IsEmpty()
|| s.BisKekSource.IsEmpty()
|| s.AesKekGenerationSource.IsEmpty()
|| s.AesKeyGenerationSource.IsEmpty()
|| s.RetailSpecificAesKeySource.IsEmpty())
if (s.DeviceKey.IsZeros()
|| s.BisKekSource.IsZeros()
|| s.AesKekGenerationSource.IsZeros()
|| s.AesKeyGenerationSource.IsZeros()
|| s.RetailSpecificAesKeySource.IsZeros())
{
return;
}
// If the user doesn't provide bis_key_source_03 we can assume it's the same as bis_key_source_02
if (s.BisKeySources[3].IsEmpty() && !s.BisKeySources[2].IsEmpty())
if (s.BisKeySources[3].IsZeros() && !s.BisKeySources[2].IsZeros())
{
s.BisKeySources[3] = s.BisKeySources[2];
}
Aes.DecryptEcb128(s.RetailSpecificAesKeySource, kek, s.DeviceKey);
if (!s.BisKeySources[0].IsEmpty()) Aes.DecryptEcb128(s.BisKeySources[0], s.BisKeys[0], kek);
if (!s.BisKeySources[0].IsZeros()) Aes.DecryptEcb128(s.BisKeySources[0], s.BisKeys[0], kek);
GenerateKek(s.DeviceKey, s.BisKekSource, kek, s.AesKekGenerationSource, s.AesKeyGenerationSource);
for (int i = 1; i < 4; i++)
{
if (!s.BisKeySources[i].IsEmpty())
if (!s.BisKeySources[i].IsZeros())
Aes.DecryptEcb128(s.BisKeySources[i], s.BisKeys[i], kek);
}
}
private static void DerivePerFirmwareKeys(KeySet s)
{
bool haveKakSource0 = !s.KeyAreaKeyApplicationSource.IsEmpty();
bool haveKakSource1 = !s.KeyAreaKeyOceanSource.IsEmpty();
bool haveKakSource2 = !s.KeyAreaKeySystemSource.IsEmpty();
bool haveTitleKekSource = !s.TitleKekSource.IsEmpty();
bool havePackage2KeySource = !s.Package2KeySource.IsEmpty();
bool haveKakSource0 = !s.KeyAreaKeyApplicationSource.IsZeros();
bool haveKakSource1 = !s.KeyAreaKeyOceanSource.IsZeros();
bool haveKakSource2 = !s.KeyAreaKeySystemSource.IsZeros();
bool haveTitleKekSource = !s.TitleKekSource.IsZeros();
bool havePackage2KeySource = !s.Package2KeySource.IsZeros();
for (int i = 0; i < KeySet.KeyRevisionCount; i++)
{
if (s.MasterKeys[i].IsEmpty())
if (s.MasterKeys[i].IsZeros())
{
continue;
}
@ -331,7 +331,7 @@ namespace LibHac.Common.Keys
private static void DeriveNcaHeaderKey(KeySet s)
{
if (s.HeaderKekSource.IsEmpty() || s.HeaderKeySource.IsEmpty() || s.MasterKeys[0].IsEmpty()) return;
if (s.HeaderKekSource.IsZeros() || s.HeaderKeySource.IsZeros() || s.MasterKeys[0].IsZeros()) return;
var headerKek = new AesKey();
@ -362,7 +362,7 @@ namespace LibHac.Common.Keys
}
// Derive sd card save key
if (!s.SeedUniqueSaveMacKekSource.IsEmpty() && !s.SeedUniqueSaveMacKeySource.IsEmpty())
if (!s.SeedUniqueSaveMacKekSource.IsZeros() && !s.SeedUniqueSaveMacKeySource.IsZeros())
{
var keySource = new AesKey();
@ -383,7 +383,7 @@ namespace LibHac.Common.Keys
Aes.DecryptEcb128(kekSeed, kek, key);
Aes.DecryptEcb128(src, srcKek, kek);
if (!keySeed.IsEmpty)
if (!keySeed.IsZeros())
{
Aes.DecryptEcb128(keySeed, dest, srcKek);
}

View file

@ -22,7 +22,7 @@ namespace LibHac.Crypto
public readonly ReadOnlySpan<ulong> DataRo64 => SpanHelpers.CreateReadOnlySpan(in _ulong, Size / sizeof(ulong));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool IsEmpty() => (DataRo64[0] | DataRo64[1]) == 0;
public readonly bool IsZeros() => (DataRo64[0] | DataRo64[1]) == 0;
public static implicit operator Span<byte>(in AesKey value) => Unsafe.AsRef(in value).Data;
@ -58,7 +58,7 @@ namespace LibHac.Crypto
public static implicit operator ReadOnlySpan<byte>(in AesXtsKey value) => value.DataRo;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool IsEmpty() => (DataRo64[0] | DataRo64[1] | DataRo64[2] | DataRo64[3]) == 0;
public readonly bool IsZeros() => (DataRo64[0] | DataRo64[1] | DataRo64[2] | DataRo64[3]) == 0;
public override readonly string ToString() => DataRo.ToHexString();
}
@ -78,7 +78,7 @@ namespace LibHac.Crypto
public readonly ReadOnlySpan<ulong> DataRo64 => SpanHelpers.CreateReadOnlySpan(in _ulong, Size / sizeof(ulong));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool IsEmpty() => (DataRo64[0] | DataRo64[1]) == 0;
public readonly bool IsZeros() => (DataRo64[0] | DataRo64[1]) == 0;
public static implicit operator Span<byte>(in AesIv value) => Unsafe.AsRef(in value).Data;
public static implicit operator ReadOnlySpan<byte>(in AesIv value) => value.DataRo;
@ -105,7 +105,7 @@ namespace LibHac.Crypto
public readonly ReadOnlySpan<ulong> DataRo64 => SpanHelpers.CreateReadOnlySpan(in _ulong, Size / sizeof(ulong));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool IsEmpty() => (DataRo64[0] | DataRo64[1]) == 0;
public readonly bool IsZeros() => (DataRo64[0] | DataRo64[1]) == 0;
public static implicit operator Span<byte>(in AesCmac value) => Unsafe.AsRef(in value).Data;
public static implicit operator ReadOnlySpan<byte>(in AesCmac value) => value.DataRo;

View file

@ -63,7 +63,7 @@ namespace LibHac.FsSystem
if (Type == IntegrityStorageType.Save)
{
if (Utilities.IsEmpty(hashBuffer))
if (Utilities.IsZeros(hashBuffer))
{
destination.Clear();
BlockValidities[blockIndex] = Validity.Valid;
@ -144,7 +144,7 @@ namespace LibHac.FsSystem
source.CopyTo(dataBuffer);
byte[] hash = DoHash(dataBuffer, 0, toWrite);
if (Type == IntegrityStorageType.Save && source.IsEmpty())
if (Type == IntegrityStorageType.Save && source.IsZeros())
{
Array.Clear(hash, 0, DigestSize);
}
@ -207,7 +207,7 @@ namespace LibHac.FsSystem
long hashPos = i * DigestSize;
HashStorage.Read(hashPos, digest).ThrowIfFailure();
if (!Utilities.IsEmpty(digest)) continue;
if (!Utilities.IsZeros(digest)) continue;
int dataOffset = i * SectorSize;
BaseStorage.Fill(SaveDataFileSystem.TrimFillValue, dataOffset, SectorSize);

View file

@ -45,7 +45,7 @@ namespace LibHac.FsSystem.NcaUtils
int keyRevision = Utilities.GetMasterKeyRevision(Header.KeyGeneration);
byte[] keyAreaKey = KeySet.KeyAreaKeys[keyRevision][Header.KeyAreaKeyIndex].DataRo.ToArray();
if (keyAreaKey.IsEmpty())
if (keyAreaKey.IsZeros())
{
string keyName = $"key_area_key_{KakNames[Header.KeyAreaKeyIndex]}_{keyRevision:x2}";
throw new MissingKeyException("Unable to decrypt NCA section.", keyName, KeyType.Common);
@ -73,7 +73,7 @@ namespace LibHac.FsSystem.NcaUtils
throw new MissingKeyException("Missing NCA title key.", rightsId.ToString(), KeyType.Title);
}
if (titleKek.IsEmpty())
if (titleKek.IsZeros())
{
string keyName = $"titlekek_{keyRevision:x2}";
throw new MissingKeyException("Unable to decrypt title key.", keyName, KeyType.Common);
@ -112,10 +112,10 @@ namespace LibHac.FsSystem.NcaUtils
if (Header.HasRightsId)
{
return KeySet.ExternalKeySet.Contains(new RightsId(Header.RightsId)) &&
!KeySet.TitleKeks[keyRevision].IsEmpty();
!KeySet.TitleKeks[keyRevision].IsZeros();
}
return !KeySet.KeyAreaKeys[keyRevision][Header.KeyAreaKeyIndex].IsEmpty();
return !KeySet.KeyAreaKeys[keyRevision][Header.KeyAreaKeyIndex].IsZeros();
}
public bool SectionExists(NcaSectionType type)

View file

@ -107,7 +107,7 @@ namespace LibHac.FsSystem.NcaUtils
public Span<byte> RightsId => _header.Span.Slice(NcaHeaderStruct.RightsIdOffset, NcaHeaderStruct.RightsIdSize);
public bool HasRightsId => !Utilities.IsEmpty(RightsId);
public bool HasRightsId => !Utilities.IsZeros(RightsId);
public Span<byte> GetKeyArea()
{

View file

@ -262,7 +262,7 @@ namespace LibHac.FsSystem.Save
headerStream.Position = 0x108;
headerStream.Write(hash, 0, hash.Length);
if (keySet == null || keySet.DeviceUniqueSaveMacKeys[0].IsEmpty()) return ResultFs.PreconditionViolation.Log();
if (keySet == null || keySet.DeviceUniqueSaveMacKeys[0].IsZeros()) return ResultFs.PreconditionViolation.Log();
var cmacData = new byte[0x200];
var cmac = new byte[0x10];

View file

@ -67,10 +67,10 @@ namespace LibHac
return a1.SequenceEqual(a2);
}
public static bool IsEmpty(this byte[] array) => ((ReadOnlySpan<byte>)array).IsEmpty();
public static bool IsEmpty(this Span<byte> span) => ((ReadOnlySpan<byte>)span).IsEmpty();
public static bool IsZeros(this byte[] array) => ((ReadOnlySpan<byte>)array).IsZeros();
public static bool IsZeros(this Span<byte> span) => ((ReadOnlySpan<byte>)span).IsZeros();
public static bool IsEmpty(this ReadOnlySpan<byte> span)
public static bool IsZeros(this ReadOnlySpan<byte> span)
{
for (int i = 0; i < span.Length; i++)
{

View file

@ -108,7 +108,7 @@ namespace LibHac
SelKey = reader.ReadInt32();
LimAreaPage = reader.ReadInt32();
if (keySet != null && !keySet.XciHeaderKey.IsEmpty())
if (keySet != null && !keySet.XciHeaderKey.IsZeros())
{
byte[] encHeader = reader.ReadBytes(EncryptedHeaderSize);
var decHeader = new byte[EncryptedHeaderSize];