Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ internal bool VerifyMac(
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}

// Cannot use the ArrayPool or stackalloc here because CreateHMAC needs a properly bounded array.
byte[] derived = new byte[expectedOutputSize];
Debug.Assert(expectedOutputSize <= 64); // SHA512 is the largest digest size we know about
Span<byte> derived = stackalloc byte[expectedOutputSize];


int iterationCount =
PasswordBasedEncryption.NormalizeIterationCount(MacData.Value.IterationCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,68 +191,52 @@ private static unsafe void PHash(
//
// This is called via PRF, which turns (label || seed) into seed.

byte[] secretTmp = new byte[secret.Length];
Span<byte> retSpan = ret;

// Keep secretTmp pinned the whole time it has a secret in it, so it
// doesn't get copied around during heap compaction.
fixed (byte* pinnedSecretTmp = secretTmp)
using (IncrementalHash hasher = IncrementalHash.CreateHMAC(algorithmName, secret))
{
secret.CopyTo(secretTmp);
Span<byte> a = stackalloc byte[hashOutputSize];
Span<byte> p = stackalloc byte[hashOutputSize];

try
{
Span<byte> retSpan = ret;

using (IncrementalHash hasher = IncrementalHash.CreateHMAC(algorithmName, secretTmp))
{
Span<byte> a = stackalloc byte[hashOutputSize];
Span<byte> p = stackalloc byte[hashOutputSize];

// A(1)
hasher.AppendData(prfLabel);
hasher.AppendData(prfSeed);
// A(1)
hasher.AppendData(prfLabel);
hasher.AppendData(prfSeed);

if (!hasher.TryGetHashAndReset(a, out int bytesWritten) || bytesWritten != hashOutputSize)
{
throw new CryptographicException();
}
if (!hasher.TryGetHashAndReset(a, out int bytesWritten) || bytesWritten != hashOutputSize)
{
throw new CryptographicException();
}

while (true)
{
// HMAC_hash(secret, A(i) || seed) => p
hasher.AppendData(a);
hasher.AppendData(prfLabel);
hasher.AppendData(prfSeed);
while (true)
{
// HMAC_hash(secret, A(i) || seed) => p
hasher.AppendData(a);
hasher.AppendData(prfLabel);
hasher.AppendData(prfSeed);

if (!hasher.TryGetHashAndReset(p, out bytesWritten) || bytesWritten != hashOutputSize)
{
throw new CryptographicException();
}
if (!hasher.TryGetHashAndReset(p, out bytesWritten) || bytesWritten != hashOutputSize)
{
throw new CryptographicException();
}

int len = Math.Min(p.Length, retSpan.Length);
int len = Math.Min(p.Length, retSpan.Length);

p.Slice(0, len).CopyTo(retSpan);
retSpan = retSpan.Slice(len);
p.Slice(0, len).CopyTo(retSpan);
retSpan = retSpan.Slice(len);

if (retSpan.Length == 0)
{
return;
}
if (retSpan.Length == 0)
{
return;
}

// Build the next A(i)
hasher.AppendData(a);
// Build the next A(i)
hasher.AppendData(a);

if (!hasher.TryGetHashAndReset(a, out bytesWritten) || bytesWritten != hashOutputSize)
{
throw new CryptographicException();
}
}
if (!hasher.TryGetHashAndReset(a, out bytesWritten) || bytesWritten != hashOutputSize)
{
throw new CryptographicException();
}
}
finally
{
Array.Clear(secretTmp, 0, secretTmp.Length);
}
}
}
}
Expand Down