Use Sha256Generator throughout the library

This commit is contained in:
Alex Barney 2019-11-26 11:40:08 -06:00
parent 1efcf3327c
commit e18481b3b7
11 changed files with 76 additions and 59 deletions

View file

@ -2,7 +2,7 @@
using System;
using System.Numerics;
using System.Security.Cryptography;
using LibHac.Crypto;
namespace LibHac.Compatibility
{
@ -17,7 +17,6 @@ namespace LibHac.Compatibility
const int saltOffset = hashOffset - digestLen;
const int padEnd = saltOffset - 1;
SHA256 sha = SHA256.Create();
var message = new byte[rsaLen];
BigInteger decInt = BigInteger.ModPow(CryptoOld.GetBigInteger(signature), new BigInteger(65537), CryptoOld.GetBigInteger(modulus));
@ -33,9 +32,12 @@ namespace LibHac.Compatibility
ref byte seed = ref hashBuf[0x23];
Span<byte> digestBuffer = stackalloc byte[Sha256.DigestSize];
for (int i = 0; i < hashOffset; i += 0x20)
{
Util.XorArrays(message.AsSpan(i, digestLen), sha.ComputeHash(hashBuf));
Sha256.GenerateSha256Hash(hashBuf, digestBuffer);
Util.XorArrays(message.AsSpan(i, digestLen), digestBuffer);
seed++;
}
@ -46,14 +48,21 @@ namespace LibHac.Compatibility
return false;
}
var prefix = new byte[8];
byte[] digest = sha.ComputeHash(data);
Span<byte> prefix = stackalloc byte[8];
Span<byte> digest = stackalloc byte[Sha256.DigestSize];
sha.TransformBlock(prefix, 0, prefix.Length, null, 0);
sha.TransformBlock(digest, 0, digestLen, null, 0);
sha.TransformFinalBlock(message, saltOffset, digestLen);
Sha256.GenerateSha256Hash(data, digest);
return Util.SpansEqual(hashBuf.AsSpan(0, 0x20), sha.Hash);
IHash sha2 = Sha256.CreateSha256Generator();
sha2.Initialize();
sha2.Update(prefix);
sha2.Update(digest);
sha2.Update(message.AsSpan(saltOffset, digestLen));
sha2.GetHash(digest);
return Util.SpansEqual(hashBuf.AsSpan(0, 0x20), digest);
}
}
}

View file

@ -7,6 +7,10 @@ namespace LibHac.Crypto
{
public const int DigestSize = 0x20;
/// <summary>
/// Creates an uninitialized SHA-256 <see cref="IHash"/> object.
/// </summary>
/// <returns> The new uninitialized SHA-256 <see cref="IHash"/> object.</returns>
public static IHash CreateSha256Generator()
{
return new Sha256Generator();

View file

@ -9,25 +9,6 @@ namespace LibHac
public static class CryptoOld
{
internal const int Aes128Size = 0x10;
internal const int Sha256DigestSize = 0x20;
public static Validity CheckMemoryHashTable(byte[] data, byte[] hash, int offset, int count)
{
Validity comp;
using (SHA256 sha = SHA256.Create())
{
comp = Util.ArraysEqual(hash, sha.ComputeHash(data, offset, count)) ? Validity.Valid : Validity.Invalid;
}
return comp;
}
public static byte[] ComputeSha256(byte[] data, int offset, int count)
{
using (SHA256 sha = SHA256.Create())
{
return sha.ComputeHash(data, offset, count);
}
}
public static void DecryptEcb(byte[] key, byte[] src, int srcIndex, byte[] dest, int destIndex, int length)
{
@ -172,7 +153,7 @@ namespace LibHac
public static Validity Rsa2048PssVerify(byte[] data, byte[] signature, byte[] modulus)
{
#if NETFRAMEWORK
if (Compatibility.Env.IsMono)
if (!Compatibility.Env.IsMono)
{
return Compatibility.Rsa.Rsa2048PssVerifyMono(data, signature, modulus)
? Validity.Valid

View file

@ -1,7 +1,7 @@
using System;
using System.Buffers;
using System.IO;
using System.Security.Cryptography;
using LibHac.Crypto;
using LibHac.Fs;
using LibHac.FsSystem.Save;
@ -18,7 +18,7 @@ namespace LibHac.FsSystem
private byte[] Salt { get; }
private IntegrityStorageType Type { get; }
private readonly SHA256 _hash = SHA256.Create();
private readonly IHash _hash = Sha256.CreateSha256Generator();
private readonly object _locker = new object();
public IntegrityVerificationStorage(IntegrityVerificationInfo info, IStorage hashStorage,
@ -170,13 +170,13 @@ namespace LibHac.FsSystem
if (Type == IntegrityStorageType.Save)
{
_hash.TransformBlock(Salt, 0, Salt.Length, null, 0);
_hash.Update(Salt);
}
_hash.TransformBlock(buffer, offset, count, null, 0);
_hash.TransformFinalBlock(buffer, 0, 0);
_hash.Update(buffer.AsSpan(offset, count));
byte[] hash = _hash.Hash;
var hash = new byte[Sha256.DigestSize];
_hash.GetHash(hash);
if (Type == IntegrityStorageType.Save)
{

View file

@ -1,6 +1,7 @@
using System;
using System.Buffers.Binary;
using System.Diagnostics;
using LibHac.Crypto;
using LibHac.Fs;
namespace LibHac.FsSystem.NcaUtils
@ -98,7 +99,8 @@ namespace LibHac.FsSystem.NcaUtils
var data = new byte[size];
storage.Read(offset, data).ThrowIfFailure();
byte[] actualHash = CryptoOld.ComputeSha256(data, 0, data.Length);
var actualHash = new byte[Sha256.DigestSize];
Sha256.GenerateSha256Hash(data, actualHash);
if (Util.ArraysEqual(expectedHash, actualHash)) return Validity.Valid;

View file

@ -2,6 +2,7 @@
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using LibHac.Crypto;
using LibHac.Fs;
namespace LibHac.FsSystem.NcaUtils
@ -163,7 +164,8 @@ namespace LibHac.FsSystem.NcaUtils
// ReSharper disable once ImpureMethodCallOnReadonlyValueField
Memory<byte> headerData = _header.Slice(offset, NcaHeaderStruct.FsHeaderSize);
byte[] actualHash = CryptoOld.ComputeSha256(headerData.ToArray(), 0, NcaHeaderStruct.FsHeaderSize);
Span<byte> actualHash = stackalloc byte[Sha256.DigestSize];
Sha256.GenerateSha256Hash(headerData.Span, actualHash);
if (!Util.SpansEqual(expectedHash, actualHash))
{

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using LibHac.Crypto;
using LibHac.Fs;
namespace LibHac.FsSystem
@ -164,7 +165,7 @@ namespace LibHac.FsSystem
{
HashedRegionSize = reader.ReadInt32();
HashedRegionOffset = reader.ReadInt64();
Hash = reader.ReadBytes(CryptoOld.Sha256DigestSize);
Hash = reader.ReadBytes(Sha256.DigestSize);
}
else
{

View file

@ -2,8 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using LibHac.Crypto;
using LibHac.Fs;
namespace LibHac.FsSystem
@ -23,7 +23,8 @@ namespace LibHac.FsSystem
/// </summary>
public PartitionFileSystemBuilder(IFileSystem input)
{
foreach (DirectoryEntryEx entry in input.EnumerateEntries().OrderBy(x => x.FullPath, StringComparer.Ordinal))
foreach (DirectoryEntryEx entry in input.EnumerateEntries().Where(x => x.Type == DirectoryEntryType.File)
.OrderBy(x => x.FullPath, StringComparer.Ordinal))
{
input.OpenFile(out IFile file, entry.FullPath, OpenMode.Read).ThrowIfFailure();
@ -144,22 +145,25 @@ namespace LibHac.FsSystem
private void CalculateHashes()
{
using (SHA256 sha = SHA256.Create())
IHash sha = Sha256.CreateSha256Generator();
foreach (Entry entry in Entries)
{
foreach (Entry entry in Entries)
if (entry.HashLength == 0) entry.HashLength = 0x200;
var data = new byte[entry.HashLength];
entry.File.Read(out long bytesRead, entry.HashOffset, data);
if (bytesRead != entry.HashLength)
{
if (entry.HashLength == 0) entry.HashLength = 0x200;
var data = new byte[entry.HashLength];
entry.File.Read(out long bytesRead, entry.HashOffset, data);
if (bytesRead != entry.HashLength)
{
throw new ArgumentOutOfRangeException();
}
entry.Hash = sha.ComputeHash(data);
throw new ArgumentOutOfRangeException();
}
entry.Hash = new byte[Sha256.DigestSize];
sha.Initialize();
sha.Update(data);
sha.GetHash(entry.Hash);
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using LibHac.Crypto;
using LibHac.Fs;
namespace LibHac.FsSystem.Save
@ -81,7 +82,10 @@ namespace LibHac.FsSystem.Save
MasterHash = storage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize);
HeaderHashValidity = CryptoOld.CheckMemoryHashTable(Data, Layout.Hash, 0x300, 0x3d00);
Span<byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize];
Sha256.GenerateSha256Hash(Data.AsSpan(0x300, 0x3d00), actualHeaderHash);
HeaderHashValidity = Util.SpansEqual(Layout.Hash, actualHeaderHash) ? Validity.Valid : Validity.Invalid;
SignatureValidity = ValidateSignature(keyset);
}

View file

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.IO;
using LibHac.Crypto;
using LibHac.Fs;
namespace LibHac.FsSystem.Save
@ -252,7 +253,9 @@ namespace LibHac.FsSystem.Save
headerStream.Position = 0x300;
headerStream.Read(hashData, 0, hashData.Length);
byte[] hash = CryptoOld.ComputeSha256(hashData, 0, hashData.Length);
var hash = new byte[Sha256.DigestSize];
Sha256.GenerateSha256Hash(hashData, hash);
headerStream.Position = 0x108;
headerStream.Write(hash, 0, hash.Length);

View file

@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Text;
using LibHac.Crypto;
using LibHac.Fs;
namespace LibHac
@ -99,8 +100,8 @@ namespace LibHac
Array.Reverse(AesCbcIv);
RootPartitionOffset = reader.ReadInt64();
RootPartitionHeaderSize = reader.ReadInt64();
RootPartitionHeaderHash = reader.ReadBytes(CryptoOld.Sha256DigestSize);
InitialDataHash = reader.ReadBytes(CryptoOld.Sha256DigestSize);
RootPartitionHeaderHash = reader.ReadBytes(Sha256.DigestSize);
InitialDataHash = reader.ReadBytes(Sha256.DigestSize);
SelSec = reader.ReadInt32();
SelT1Key = reader.ReadInt32();
SelKey = reader.ReadInt32();
@ -128,10 +129,16 @@ namespace LibHac
}
}
ImageHash = CryptoOld.ComputeSha256(sigData, 0, sigData.Length);
ImageHash = new byte[Sha256.DigestSize];
Sha256.GenerateSha256Hash(sigData, ImageHash);
reader.BaseStream.Position = RootPartitionOffset;
PartitionFsHeaderValidity = CryptoOld.CheckMemoryHashTable(reader.ReadBytes((int)RootPartitionHeaderSize), RootPartitionHeaderHash, 0, (int)RootPartitionHeaderSize);
byte[] headerBytes = reader.ReadBytes((int) RootPartitionHeaderSize);
Span<byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize];
Sha256.GenerateSha256Hash(headerBytes, actualHeaderHash);
PartitionFsHeaderValidity = Util.SpansEqual(RootPartitionHeaderHash, actualHeaderHash) ? Validity.Valid : Validity.Invalid;
}
}
}