in net/JetBrains.SignatureVerifier/src/Crypt/AppleSignatureVerifier.cs [71:138]
public VerifySignatureResult VerifyCDHashes(Stream stream, IEnumerable<CDHash> cdHashesInfo, SignedMessage sectionSignature)
{
Dictionary<AlgorithmIdentifier, byte[]> hashesToVerify = new Dictionary<AlgorithmIdentifier, byte[]>();
foreach (var cdHash in cdHashesInfo)
{
var hashId = new AlgorithmIdentifier(DigestUtilities.GetObjectIdentifier(cdHash.HashName));
var hashValue = HashUtil.ComputeHash(stream, cdHash.ComputeHashInfo, hashId);
hashesToVerify.Add(hashId, hashValue);
}
// Checking APPLE_HASH_AGILITY_V2 attribute for CDHash values
var expectedCdHashValues = GetHashAgilityV2Hashes(sectionSignature);
foreach (var cdHashValue in expectedCdHashValues)
{
AlgorithmIdentifier algId = cdHashValue.DigestAlgorithm;
if (hashesToVerify.ContainsKey(algId))
{
var hashValue = hashesToVerify[algId];
var expectedDigest = cdHashValue.GetDigest();
int length = Math.Min(expectedDigest.Length, hashValue.Length);
bool equals = Arrays.FixedTimeEquals( length, expectedDigest, 0, hashValue, 0);
if (equals)
hashesToVerify.Remove(algId);
else
{
_logger?.Warning("Apple signature verification failed: CDHash value doesn't match the expected value");
return new VerifySignatureResult(VerifySignatureStatus.InvalidFileHash);
}
}
}
if (hashesToVerify.Count == 0)
return VerifySignatureResult.Valid;
// Fallback for older APPLE_HASH_AGILITY attribute
var expectedHashValues = GetHashAgilityV1Hashes(sectionSignature);
foreach (var expectedHashValue in expectedHashValues)
{
AlgorithmIdentifier foundKey = null;
foreach (var hashToVerifyKeyPair in hashesToVerify)
{
int length = Math.Min(expectedHashValue.Length, hashToVerifyKeyPair.Value.Length);
if (Arrays.FixedTimeEquals(length, expectedHashValue, 0, hashToVerifyKeyPair.Value, 0))
{
foundKey = hashToVerifyKeyPair.Key;
break;
}
}
if (foundKey != null)
hashesToVerify.Remove(foundKey);
}
if (hashesToVerify.Count > 0)
_logger?.Warning("Apple signature verification failed: CDHash value doesn't match the expected value");
return hashesToVerify.Count == 0 ? VerifySignatureResult.Valid : new VerifySignatureResult(VerifySignatureStatus.InvalidFileHash);
}