mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Tweak how IVFC validation is done
This commit is contained in:
parent
da5eec1b3d
commit
f8e7c00ef4
2 changed files with 48 additions and 28 deletions
|
@ -39,31 +39,33 @@ namespace LibHac
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks the hashes of any unchecked blocks and returns the <see cref="Validity"/> of the hash level.
|
/// Checks the hashes of any unchecked blocks and returns the <see cref="Validity"/> of the data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="level">The level of hierarchical hashes to check.</param>
|
|
||||||
/// <param name="returnOnError">If <see langword="true"/>, return as soon as an invalid block is found.</param>
|
/// <param name="returnOnError">If <see langword="true"/>, return as soon as an invalid block is found.</param>
|
||||||
/// <param name="logger">An optional <see cref="IProgressReport"/> for reporting progress.</param>
|
/// <param name="logger">An optional <see cref="IProgressReport"/> for reporting progress.</param>
|
||||||
/// <returns>The <see cref="Validity"/> of the data of the specified hash level.</returns>
|
/// <returns>The <see cref="Validity"/> of the data of the specified hash level.</returns>
|
||||||
public Validity ValidateLevel(int level, bool returnOnError, IProgressReport logger = null)
|
public Validity Validate(bool returnOnError, IProgressReport logger = null)
|
||||||
{
|
{
|
||||||
Validity[] validities = LevelValidities[level];
|
Validity[] validities = LevelValidities[LevelValidities.Length - 1];
|
||||||
IntegrityVerificationStream levelStream = IntegrityStreams[level];
|
IntegrityVerificationStream stream = IntegrityStreams[IntegrityStreams.Length - 1];
|
||||||
|
|
||||||
// The original position of the stream must be restored when we're done validating
|
// Restore the original position of the stream when we're done validating
|
||||||
long initialPosition = levelStream.Position;
|
long initialPosition = stream.Position;
|
||||||
|
|
||||||
var buffer = new byte[levelStream.SectorSize];
|
long blockSize = stream.SectorSize;
|
||||||
|
int blockCount = (int)Util.DivideByRoundUp(Length, blockSize);
|
||||||
|
|
||||||
|
var buffer = new byte[blockSize];
|
||||||
var result = Validity.Valid;
|
var result = Validity.Valid;
|
||||||
|
|
||||||
logger?.SetTotal(levelStream.SectorCount);
|
logger?.SetTotal(blockCount);
|
||||||
|
|
||||||
for (int i = 0; i < levelStream.SectorCount; i++)
|
for (int i = 0; i < blockCount; i++)
|
||||||
{
|
{
|
||||||
if (validities[i] == Validity.Unchecked)
|
if (validities[i] == Validity.Unchecked)
|
||||||
{
|
{
|
||||||
levelStream.Position = (long)levelStream.SectorSize * i;
|
stream.Position = blockSize * i;
|
||||||
levelStream.Read(buffer, 0, buffer.Length, IntegrityCheckLevel.IgnoreOnInvalid);
|
stream.Read(buffer, 0, buffer.Length, IntegrityCheckLevel.IgnoreOnInvalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (validities[i] == Validity.Invalid)
|
if (validities[i] == Validity.Invalid)
|
||||||
|
@ -76,7 +78,7 @@ namespace LibHac
|
||||||
}
|
}
|
||||||
|
|
||||||
logger?.SetTotal(0);
|
logger?.SetTotal(0);
|
||||||
levelStream.Position = initialPosition;
|
stream.Position = initialPosition;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -489,25 +489,43 @@ namespace LibHac
|
||||||
if (stream == null) return Validity.Unchecked;
|
if (stream == null) return Validity.Unchecked;
|
||||||
|
|
||||||
if (!quiet) logger?.LogMessage($"Verifying section {index}...");
|
if (!quiet) logger?.LogMessage($"Verifying section {index}...");
|
||||||
|
Validity validity = stream.Validate(true, logger);
|
||||||
|
|
||||||
for (int i = 0; i < stream.Levels.Length - 1; i++)
|
if (hashType == NcaHashType.Ivfc)
|
||||||
{
|
{
|
||||||
if (!quiet) logger?.LogMessage($" Verifying Hash Level {i}...");
|
SetIvfcLevelValidities(stream, sect.Header.IvfcInfo);
|
||||||
Validity levelValidity = stream.ValidateLevel(i, true, logger);
|
}
|
||||||
|
else if (hashType == NcaHashType.Sha256)
|
||||||
if (hashType == NcaHashType.Ivfc)
|
{
|
||||||
{
|
sect.Header.Sha256Info.HashValidity = validity;
|
||||||
sect.Header.IvfcInfo.LevelHeaders[i].HashValidity = levelValidity;
|
|
||||||
}
|
|
||||||
else if (hashType == NcaHashType.Sha256 && i == stream.Levels.Length - 2)
|
|
||||||
{
|
|
||||||
sect.Header.Sha256Info.HashValidity = levelValidity;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (levelValidity == Validity.Invalid) return Validity.Invalid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Validity.Valid;
|
return validity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetIvfcLevelValidities(HierarchicalIntegrityVerificationStream stream, IvfcHeader header)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < stream.Levels.Length - 1; i++)
|
||||||
|
{
|
||||||
|
Validity[] level = stream.LevelValidities[i];
|
||||||
|
var levelValidity = Validity.Valid;
|
||||||
|
|
||||||
|
foreach (Validity block in level)
|
||||||
|
{
|
||||||
|
if (block == Validity.Invalid)
|
||||||
|
{
|
||||||
|
levelValidity = Validity.Invalid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block == Validity.Unchecked && levelValidity != Validity.Invalid)
|
||||||
|
{
|
||||||
|
levelValidity = Validity.Unchecked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header.LevelHeaders[i].HashValidity = levelValidity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue