--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+
+namespace System.Security.Cryptography
+{
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "Weak algorithms are used as instructed by the caller")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "Weak algorithms are used as instructed by the caller")]
+ internal static class HashOneShotHelpers
+ {
+ public static int MacData(
+ HashAlgorithmName hashAlgorithm,
+ ReadOnlySpan<byte> key,
+ ReadOnlySpan<byte> source,
+ Span<byte> destination)
+ {
+ if (hashAlgorithm == HashAlgorithmName.SHA256)
+ {
+ return HMACSHA256.HashData(key, source, destination);
+ }
+ else if (hashAlgorithm == HashAlgorithmName.SHA1)
+ {
+ return HMACSHA1.HashData(key, source, destination);
+ }
+ else if (hashAlgorithm == HashAlgorithmName.SHA512)
+ {
+ return HMACSHA512.HashData(key, source, destination);
+ }
+ else if (hashAlgorithm == HashAlgorithmName.SHA384)
+ {
+ return HMACSHA384.HashData(key, source, destination);
+ }
+ else if (hashAlgorithm == HashAlgorithmName.MD5)
+ {
+ return HMACMD5.HashData(key, source, destination);
+ }
+
+ throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name));
+ }
+ }
+}
Link="Common\System\Security\Cryptography\EccKeyFormatHelper.cs" />
<Compile Include="$(CommonPath)System\Security\Cryptography\KeyBlobHelpers.cs"
Link="Common\System\Security\Cryptography\KeyBlobHelpers.cs" />
+ <Compile Include="$(CommonPath)System\Security\Cryptography\HashOneShotHelpers.cs"
+ Link="Common\System\Security\Cryptography\HashOneShotHelpers.cs" />
<Compile Include="$(CommonPath)System\Security\Cryptography\KeyFormatHelper.cs"
Link="Common\System\Security\Cryptography\KeyFormatHelper.cs" />
<Compile Include="$(CommonPath)System\Security\Cryptography\KeySizeHelpers.cs"
private static void Extract(HashAlgorithmName hashAlgorithmName, int hashLength, ReadOnlySpan<byte> ikm, ReadOnlySpan<byte> salt, Span<byte> prk)
{
Debug.Assert(HashLength(hashAlgorithmName) == hashLength);
-
- using (IncrementalHash hmac = IncrementalHash.CreateHMAC(hashAlgorithmName, salt))
- {
- hmac.AppendData(ikm);
- GetHashAndReset(hmac, prk);
- }
+ int written = HashOneShotHelpers.MacData(hashAlgorithmName, salt, ikm, prk);
+ Debug.Assert(written == prk.Length, $"Bytes written is {written} bytes which does not match output length ({prk.Length} bytes)");
}
/// <summary>
return new ArraySegment<byte>(authSafe, 0, authSafeLength);
}
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "HMACSHA1 is required for compat with other platforms")]
private static unsafe byte[] MacAndEncode(
AsnWriter tmpWriter,
ReadOnlyMemory<byte> encodedAuthSafe,
ReadOnlySpan<char> passwordSpan)
{
- // Windows/macOS compatibility: Use HMAC-SHA-1,
- // other algorithms may not be understood
- byte[] macKey = new byte[20];
- Span<byte> macSalt = stackalloc byte[20];
- Span<byte> macSpan = stackalloc byte[20];
- HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA1;
+ const int MacSize = 160 / 8; // HMAC-SHA1 is 160 bits.
+ Span<byte> macKey = stackalloc byte[MacSize];
+ Span<byte> macSalt = stackalloc byte[MacSize];
+ Span<byte> macSpan = stackalloc byte[MacSize];
RandomNumberGenerator.Fill(macSalt);
- fixed (byte* macKeyPtr = macKey)
- {
- Span<byte> macKeySpan = macKey;
-
- Pkcs12Kdf.DeriveMacKey(
- passwordSpan,
- hashAlgorithm,
- s_windowsPbe.IterationCount,
- macSalt,
- macKeySpan);
-
- using (IncrementalHash mac = IncrementalHash.CreateHMAC(hashAlgorithm, macKey))
- {
- mac.AppendData(encodedAuthSafe.Span);
+ Pkcs12Kdf.DeriveMacKey(
+ passwordSpan,
+ HashAlgorithmName.SHA1,
+ s_windowsPbe.IterationCount,
+ macSalt,
+ macKey);
- if (!mac.TryGetHashAndReset(macSpan, out int bytesWritten) || bytesWritten != macSpan.Length)
- {
- Debug.Fail($"TryGetHashAndReset wrote {bytesWritten} of {macSpan.Length} bytes");
- throw new CryptographicException();
- }
- }
+ int bytesWritten = HMACSHA1.HashData(macKey, encodedAuthSafe.Span, macSpan);
- CryptographicOperations.ZeroMemory(macKeySpan);
+ if (bytesWritten != MacSize)
+ {
+ Debug.Fail($"HMACSHA1.HashData wrote {bytesWritten} of {MacSize} bytes");
+ throw new CryptographicException();
}
+ CryptographicOperations.ZeroMemory(macKey);
+
// https://tools.ietf.org/html/rfc7292#section-4
//
// PFX ::= SEQUENCE {