Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SHAKE128 and SHAKE256 #87099

Merged
merged 23 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5698294
Quick sketch for SHAKE
vcsjones Mar 25, 2023
9e1f41f
Quick implementation for Windows
vcsjones Mar 25, 2023
cdbdc0f
SHAKE128 progress on Windows
vcsjones Jun 2, 2023
3ba6ff2
SHAKE128 complete on Windows
vcsjones Jun 2, 2023
dea682d
Fix test to not use constrained new() for testing exceptions
vcsjones Jun 2, 2023
be624e4
Light up XOF one-shots on OpenSSL
vcsjones Jun 2, 2023
6867809
Fix typo in comment
vcsjones Jun 2, 2023
d43c293
Bring up SHAKE256
vcsjones Jun 3, 2023
01b106c
Change exception types.
vcsjones Jun 3, 2023
1c56ca2
Code review feedback, and some analyzer fixes
vcsjones Jun 8, 2023
a0ac765
Add tests for empty scenarios
vcsjones Jun 8, 2023
8f61aa1
Fix indentation and test object disposed for zero outputs
vcsjones Jun 8, 2023
ecfe5a8
Code review feedback
vcsjones Jun 8, 2023
fdd579d
Use span marshaller
vcsjones Jun 8, 2023
ae95f1b
Work around OpenSSL 1.1.1 bug with zero length digests in EVP_DigestF…
vcsjones Jun 9, 2023
4226620
Test that resetting with an empty buffer actually resets
vcsjones Jun 9, 2023
79cf398
Test and fix NULL buffers for shake destinations
vcsjones Jun 9, 2023
cf5886f
Fix Window's handling of null destination buffers for zero length out…
vcsjones Jun 9, 2023
4b63b45
Fix extra line
vcsjones Jun 9, 2023
2c19680
Use OPENSSL_cleanse
vcsjones Jun 9, 2023
6c52426
Cleanup duplicate GetNonNullPinnableReference
vcsjones Jun 12, 2023
d175ad5
Merge remote-tracking branch 'ms/main' into xof
vcsjones Jun 13, 2023
2407d8b
Merge remote-tracking branch 'ms/main' into xof
vcsjones Jun 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ internal static partial class Crypto
HashAlgorithmNames.MD5 => EvpMd5(),
HashAlgorithmNames.SHA3_256 or HashAlgorithmNames.SHA3_384 or HashAlgorithmNames.SHA3_512 =>
throw new PlatformNotSupportedException(),
HashAlgorithmNames.SHAKE128 or HashAlgorithmNames.SHAKE256 => throw new PlatformNotSupportedException(),
_ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId))
};

Expand All @@ -70,6 +71,8 @@ internal static bool HashAlgorithmSupported(string hashAlgorithmId)
case HashAlgorithmNames.SHA3_256:
case HashAlgorithmNames.SHA3_384:
case HashAlgorithmNames.SHA3_512:
case HashAlgorithmNames.SHAKE128:
case HashAlgorithmNames.SHAKE256:
return false;
default:
throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using Microsoft.Win32.SafeHandles;
Expand Down Expand Up @@ -37,6 +38,34 @@ internal static partial class Crypto
[LibraryImport(Libraries.AndroidCryptoNative, EntryPoint = "CryptoNative_GetMaxMdSize")]
private static partial int GetMaxMdSize();

internal static unsafe int EvpDigestXOFOneShot(IntPtr type, ReadOnlySpan<byte> source, Span<byte> destination)
{
// The partial needs to match the OpenSSL parameters.
_ = type;
_ = source;
_ = destination;
Debug.Fail("Should have validated that XOF is not supported before getting here.");
throw new UnreachableException();
}

internal static unsafe int EvpDigestFinalXOF(SafeEvpMdCtxHandle ctx, Span<byte> destination)
{
// The partial needs to match the OpenSSL parameters.
_ = ctx;
_ = destination;
Debug.Fail("Should have validated that XOF is not supported before getting here.");
throw new UnreachableException();
}

internal static unsafe int EvpDigestCurrentXOF(SafeEvpMdCtxHandle ctx, Span<byte> destination)
{
// The partial needs to match the OpenSSL parameters.
_ = ctx;
_ = destination;
vcsjones marked this conversation as resolved.
Show resolved Hide resolved
Debug.Fail("Should have validated that XOF is not supported before getting here.");
throw new UnreachableException();
}

internal static readonly int EVP_MAX_MD_SIZE = GetMaxMdSize();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ internal static partial class Crypto
private static volatile IntPtr s_evpSha3_256;
private static volatile IntPtr s_evpSha3_384;
private static volatile IntPtr s_evpSha3_512;
private static volatile IntPtr s_evpSha3_Shake128;
private static volatile IntPtr s_evpSha3_Shake256;
private static volatile bool s_evpSha3_256Cached;
private static volatile bool s_evpSha3_384Cached;
private static volatile bool s_evpSha3_512Cached;
private static volatile bool s_evpSha3_Shake128Cached;
private static volatile bool s_evpSha3_Shake256Cached;

[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpMd5();
Expand Down Expand Up @@ -93,6 +97,33 @@ private static IntPtr EvpSha3_512()
return s_evpSha3_512;
}

[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpShake128();

private static IntPtr EvpShake128()
{
if (!s_evpSha3_Shake128Cached)
{
s_evpSha3_Shake128 = CryptoNative_EvpShake128();
s_evpSha3_Shake128Cached = true;
}

return s_evpSha3_Shake128;
}

[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpShake256();

private static IntPtr EvpShake256()
{
if (!s_evpSha3_Shake256Cached)
{
s_evpSha3_Shake256 = CryptoNative_EvpShake256();
s_evpSha3_Shake256Cached = true;
}

return s_evpSha3_Shake256;
}

internal static IntPtr HashAlgorithmToEvp(string hashAlgorithmId)
{
Expand All @@ -111,6 +142,12 @@ internal static IntPtr HashAlgorithmToEvp(string hashAlgorithmId)
case HashAlgorithmNames.SHA3_512:
IntPtr sha3_512 = EvpSha3_512();
return sha3_512 != 0 ? sha3_512 : throw new PlatformNotSupportedException();
case HashAlgorithmNames.SHAKE128:
IntPtr shake128 = EvpShake128();
return shake128 != 0 ? shake128 : throw new PlatformNotSupportedException();
case HashAlgorithmNames.SHAKE256:
IntPtr shake256 = EvpShake256();
return shake256 != 0 ? shake256 : throw new PlatformNotSupportedException();
case nameof(HashAlgorithmName.MD5): return EvpMd5();
default:
throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId));
Expand All @@ -133,6 +170,10 @@ internal static bool HashAlgorithmSupported(string hashAlgorithmId)
return EvpSha3_384() != 0;
case HashAlgorithmNames.SHA3_512:
return EvpSha3_512() != 0;
case HashAlgorithmNames.SHAKE128:
return EvpShake128() != 0;
case HashAlgorithmNames.SHAKE256:
return EvpShake256() != 0;
default:
throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
Expand All @@ -25,12 +24,21 @@ internal static partial class Crypto
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestFinalEx")]
internal static partial int EvpDigestFinalEx(SafeEvpMdCtxHandle ctx, ref byte md, ref uint s);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestFinalXOF")]
private static unsafe partial int EvpDigestFinalXOF(SafeEvpMdCtxHandle ctx, Span<byte> md, uint len);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestCurrentXOF")]
private static unsafe partial int EvpDigestCurrentXOF(SafeEvpMdCtxHandle ctx, Span<byte> md, uint len);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestCurrent")]
internal static partial int EvpDigestCurrent(SafeEvpMdCtxHandle ctx, ref byte md, ref uint s);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestOneShot")]
internal static unsafe partial int EvpDigestOneShot(IntPtr type, byte* source, int sourceSize, byte* md, uint* mdSize);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestXOFOneShot")]
private static unsafe partial int EvpDigestXOFOneShot(IntPtr type, ReadOnlySpan<byte> source, int sourceSize, Span<byte> md, uint len);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdSize")]
internal static partial int EvpMdSize(IntPtr md);

Expand All @@ -39,13 +47,13 @@ internal static partial class Crypto

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Pbkdf2")]
private static unsafe partial int Pbkdf2(
byte* pPassword,
ReadOnlySpan<byte> pPassword,
int passwordLength,
byte* pSalt,
ReadOnlySpan<byte> pSalt,
int saltLength,
int iterations,
IntPtr digestEvp,
byte* pDestination,
Span<byte> pDestination,
int destinationLength);

internal static unsafe int Pbkdf2(
Expand All @@ -55,20 +63,30 @@ internal static partial class Crypto
IntPtr digestEvp,
Span<byte> destination)
{
fixed (byte* pPassword = password)
fixed (byte* pSalt = salt)
fixed (byte* pDestination = destination)
{
return Pbkdf2(
pPassword,
password.Length,
pSalt,
salt.Length,
iterations,
digestEvp,
pDestination,
destination.Length);
}
return Pbkdf2(
password,
password.Length,
salt,
salt.Length,
iterations,
digestEvp,
destination,
destination.Length);
}

internal static unsafe int EvpDigestFinalXOF(SafeEvpMdCtxHandle ctx, Span<byte> destination)
{
return EvpDigestFinalXOF(ctx, destination, (uint)destination.Length);
}

internal static unsafe int EvpDigestCurrentXOF(SafeEvpMdCtxHandle ctx, Span<byte> destination)
{
return EvpDigestCurrentXOF(ctx, destination, (uint)destination.Length);
}

internal static unsafe int EvpDigestXOFOneShot(IntPtr type, ReadOnlySpan<byte> source, Span<byte> destination)
{
return EvpDigestXOFOneShot(type, source, source.Length, destination, (uint)destination.Length);
}

internal static readonly int EVP_MAX_MD_SIZE = GetMaxMdSize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public enum BCryptAlgPseudoHandle : uint
BCRYPT_HMAC_SHA3_256_ALG_HANDLE = 0x000003E1,
BCRYPT_HMAC_SHA3_384_ALG_HANDLE = 0x000003F1,
BCRYPT_HMAC_SHA3_512_ALG_HANDLE = 0x00000401,
BCRYPT_CSHAKE128_ALG_HANDLE = 0x00000411,
BCRYPT_CSHAKE256_ALG_HANDLE = 0x00000421,
}

internal static bool PseudoHandlesSupported { get; } =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ internal static partial class BCrypt
[LibraryImport(Libraries.BCrypt, StringMarshalling = StringMarshalling.Utf16)]
internal static partial NTSTATUS BCryptCreateHash(SafeBCryptAlgorithmHandle hAlgorithm, out SafeBCryptHashHandle phHash, IntPtr pbHashObject, int cbHashObject, ReadOnlySpan<byte> secret, int cbSecret, BCryptCreateHashFlags dwFlags);

[LibraryImport(Libraries.BCrypt, StringMarshalling = StringMarshalling.Utf16)]
internal static partial NTSTATUS BCryptCreateHash(nuint hAlgorithm, out SafeBCryptHashHandle phHash, IntPtr pbHashObject, int cbHashObject, ReadOnlySpan<byte> secret, int cbSecret, BCryptCreateHashFlags dwFlags);

[Flags]
internal enum BCryptCreateHashFlags : int
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ internal static partial class BCrypt
{
[LibraryImport(Libraries.BCrypt)]
internal static partial NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, Span<byte> pbOutput, int cbOutput, int dwFlags);

[LibraryImport(Libraries.BCrypt)]
internal static unsafe partial NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, byte* pbOutput, int cbOutput, int dwFlags);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2463,6 +2463,44 @@ public sealed partial class SHA512Managed : System.Security.Cryptography.SHA512
public sealed override void Initialize() { }
protected sealed override bool TryHashFinal(System.Span<byte> destination, out int bytesWritten) { throw null; }
}
public sealed partial class Shake128 : System.IDisposable
{
public Shake128() { }
public static bool IsSupported { get { throw null; } }
public void AppendData(byte[] data) { }
public void AppendData(System.ReadOnlySpan<byte> data) { }
public void Dispose() { }
public byte[] GetCurrentHash(int outputLength) { throw null; }
public void GetCurrentHash(System.Span<byte> destination) { }
public byte[] GetHashAndReset(int outputLength) { throw null; }
public void GetHashAndReset(System.Span<byte> destination) { }
public static byte[] HashData(byte[] source, int outputLength) { throw null; }
public static byte[] HashData(System.IO.Stream source, int outputLength) { throw null; }
public static void HashData(System.IO.Stream source, System.Span<byte> destination) { }
public static byte[] HashData(System.ReadOnlySpan<byte> source, int outputLength) { throw null; }
public static void HashData(System.ReadOnlySpan<byte> source, System.Span<byte> destination) { }
public static System.Threading.Tasks.ValueTask<byte[]> HashDataAsync(System.IO.Stream source, int outputLength, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory<byte> destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public sealed partial class Shake256 : System.IDisposable
{
public Shake256() { }
public static bool IsSupported { get { throw null; } }
public void AppendData(byte[] data) { }
public void AppendData(System.ReadOnlySpan<byte> data) { }
public void Dispose() { }
public byte[] GetCurrentHash(int outputLength) { throw null; }
public void GetCurrentHash(System.Span<byte> destination) { }
public byte[] GetHashAndReset(int outputLength) { throw null; }
public void GetHashAndReset(System.Span<byte> destination) { }
public static byte[] HashData(byte[] source, int outputLength) { throw null; }
public static byte[] HashData(System.IO.Stream source, int outputLength) { throw null; }
public static void HashData(System.IO.Stream source, System.Span<byte> destination) { }
public static byte[] HashData(System.ReadOnlySpan<byte> source, int outputLength) { throw null; }
public static void HashData(System.ReadOnlySpan<byte> source, System.Span<byte> destination) { }
public static System.Threading.Tasks.ValueTask<byte[]> HashDataAsync(System.IO.Stream source, int outputLength, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory<byte> destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public partial class SignatureDescription
{
public SignatureDescription() { }
Expand Down