Skip to content

Commit

Permalink
SHAKE Read, Reset, and Clone
Browse files Browse the repository at this point in the history
  • Loading branch information
vcsjones authored Apr 19, 2024
1 parent ce63557 commit ef465c1
Show file tree
Hide file tree
Showing 19 changed files with 639 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ internal static unsafe int EvpDigestCurrentXOF(SafeEvpMdCtxHandle ctx, Span<byte
throw new UnreachableException();
}

internal static SafeEvpMdCtxHandle EvpMdCtxCopyEx(SafeEvpMdCtxHandle ctx)
{
_ = ctx;
Debug.Fail("Should have validated that XOF is not supported before getting here.");
throw new UnreachableException();
}

internal static int EvpDigestSqueeze(SafeEvpMdCtxHandle ctx, Span<byte> destination)
{
_ = ctx;
_ = destination;
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 @@ -9,6 +9,9 @@ internal static partial class Interop
{
internal static partial class Crypto
{
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxCopyEx")]
internal static partial SafeEvpMdCtxHandle EvpMdCtxCopyEx(SafeEvpMdCtxHandle ctx);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxCreate")]
internal static partial SafeEvpMdCtxHandle EvpMdCtxCreate(IntPtr type);

Expand All @@ -18,6 +21,13 @@ internal static partial class Crypto
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestReset")]
internal static partial int EvpDigestReset(SafeEvpMdCtxHandle ctx, IntPtr type);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestSqueeze")]
private static partial int EvpDigestSqueeze(
SafeEvpMdCtxHandle ctx,
Span<byte> md,
uint len,
[MarshalAs(UnmanagedType.Bool)] out bool haveFeature);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestUpdate")]
internal static partial int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ReadOnlySpan<byte> d, int cnt);

Expand Down Expand Up @@ -89,6 +99,18 @@ internal static unsafe int EvpDigestXOFOneShot(IntPtr type, ReadOnlySpan<byte> s
return EvpDigestXOFOneShot(type, source, source.Length, destination, (uint)destination.Length);
}

internal static int EvpDigestSqueeze(SafeEvpMdCtxHandle ctx, Span<byte> destination)
{
int ret = EvpDigestSqueeze(ctx, destination, (uint)destination.Length, out bool haveFeature);

if (!haveFeature)
{
throw new PlatformNotSupportedException();
}

return ret;
}

internal static readonly int EVP_MAX_MD_SIZE = GetMaxMdSize();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2587,6 +2587,7 @@ public Shake128() { }
public static bool IsSupported { get { throw null; } }
public void AppendData(byte[] data) { }
public void AppendData(System.ReadOnlySpan<byte> data) { }
public System.Security.Cryptography.Shake128 Clone() { throw null; }
public void Dispose() { }
public byte[] GetCurrentHash(int outputLength) { throw null; }
public void GetCurrentHash(System.Span<byte> destination) { }
Expand All @@ -2599,13 +2600,17 @@ public static void HashData(System.IO.Stream source, System.Span<byte> destinati
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 byte[] Read(int outputLength) { throw null; }
public void Read(System.Span<byte> destination) { }
public void Reset() { }
}
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 System.Security.Cryptography.Shake256 Clone() { throw null; }
public void Dispose() { }
public byte[] GetCurrentHash(int outputLength) { throw null; }
public void GetCurrentHash(System.Span<byte> destination) { }
Expand All @@ -2618,6 +2623,9 @@ public static void HashData(System.IO.Stream source, System.Span<byte> destinati
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 byte[] Read(int outputLength) { throw null; }
public void Read(System.Span<byte> destination) { }
public void Reset() { }
}
public partial class SignatureDescription
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,9 @@
<data name="InvalidOperation_UnsupportedBlockSize" xml:space="preserve">
<value>The algorithm's block size is not supported.</value>
</data>
<data name="InvalidOperation_AlreadyReading" xml:space="preserve">
<value>This operation is not supported once the algorithm has started reading.</value>
</data>
<data name="NotSupported_ECDsa_Csp" xml:space="preserve">
<value>CryptoApi ECDsa keys are not supported.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ internal static LiteXof CreateXof(string hashAlgorithmId)
public int Finalize(Span<byte> destination) => throw new UnreachableException();
public void Current(Span<byte> destination) => throw new UnreachableException();
public int Reset() => throw new UnreachableException();
public LiteXof Clone() => throw new UnreachableException();
public void Read(Span<byte> destination) => throw new UnreachableException();
public void Dispose() => throw new UnreachableException();
#pragma warning restore IDE0060
#pragma warning restore CA1822
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ internal static LiteXof CreateXof(string hashAlgorithmId)
public int Finalize(Span<byte> destination) => throw new UnreachableException();
public void Current(Span<byte> destination) => throw new UnreachableException();
public int Reset() => throw new UnreachableException();
public LiteXof Clone() => throw new UnreachableException();
public void Read(Span<byte> destination) => throw new UnreachableException();
public void Dispose() => throw new UnreachableException();
#pragma warning restore IDE0060
#pragma warning restore CA1822
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ internal LiteXof(IntPtr algorithm)
Interop.Crypto.CheckValidOpenSslHandle(_ctx);
}

private LiteXof(SafeEvpMdCtxHandle ctx, IntPtr algorithm)
{
_ctx = ctx;
_algorithm = algorithm;
}

public void Append(ReadOnlySpan<byte> data)
{
if (data.IsEmpty)
Expand All @@ -70,6 +76,18 @@ public void Current(Span<byte> destination)
Check(Interop.Crypto.EvpDigestCurrentXOF(_ctx, destination));
}

public LiteXof Clone()
{
SafeEvpMdCtxHandle clone = Interop.Crypto.EvpMdCtxCopyEx(_ctx);
Interop.Crypto.CheckValidOpenSslHandle(clone);
return new LiteXof(clone, _algorithm);
}

public void Read(Span<byte> destination)
{
Check(Interop.Crypto.EvpDigestSqueeze(_ctx, destination));
}

public void Dispose()
{
_ctx.Dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,11 @@ private static void CheckStatus(NTSTATUS status)
}
}

internal struct LiteXof : ILiteHash
internal readonly struct LiteXof : ILiteHash
{
private const int BCRYPT_HASH_DONT_RESET_FLAG = 0x00000001;
private readonly nuint _algorithm;
private SafeBCryptHashHandle _hashHandle;
private readonly SafeBCryptHashHandle _hashHandle;

internal LiteXof(string algorithm)
{
Expand All @@ -173,7 +174,24 @@ internal LiteXof(string algorithm)
_ => throw FailThrow(algorithm),
};

Reset();
SafeBCryptHashHandle hashHandle;

NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash(
_algorithm,
out hashHandle,
pbHashObject: IntPtr.Zero,
cbHashObject: 0,
secret: ReadOnlySpan<byte>.Empty,
cbSecret: 0,
BCryptCreateHashFlags.None);

if (ntStatus != NTSTATUS.STATUS_SUCCESS)
{
hashHandle.Dispose();
throw Interop.BCrypt.CreateCryptographicException(ntStatus);
}

_hashHandle = hashHandle;

static Exception FailThrow(string algorithm)
{
Expand All @@ -182,7 +200,13 @@ static Exception FailThrow(string algorithm)
}
}

public readonly int HashSizeInBytes
private LiteXof(SafeBCryptHashHandle hashHandle, nuint algorithm)
{
_algorithm = algorithm;
_hashHandle = hashHandle;
}

public int HashSizeInBytes
{
get
{
Expand All @@ -191,7 +215,7 @@ public readonly int HashSizeInBytes
}
}

public readonly void Append(ReadOnlySpan<byte> data)
public void Append(ReadOnlySpan<byte> data)
{
if (data.IsEmpty)
{
Expand All @@ -206,7 +230,7 @@ public readonly void Append(ReadOnlySpan<byte> data)
}
}

public readonly unsafe int Finalize(Span<byte> destination)
public unsafe int Finalize(Span<byte> destination)
{
fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination))
{
Expand All @@ -221,36 +245,33 @@ public readonly unsafe int Finalize(Span<byte> destination)
}
}

[MemberNotNull(nameof(_hashHandle))]
public void Reset()
{
_hashHandle?.Dispose();
SafeBCryptHashHandle hashHandle;

NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash(
_algorithm,
out hashHandle,
pbHashObject: IntPtr.Zero,
cbHashObject: 0,
secret: ReadOnlySpan<byte>.Empty,
cbSecret: 0,
BCryptCreateHashFlags.None);
public void Reset() => Finalize(Span<byte>.Empty);

if (ntStatus != NTSTATUS.STATUS_SUCCESS)
public unsafe void Current(Span<byte> destination)
{
using (SafeBCryptHashHandle tmpHash = Interop.BCrypt.BCryptDuplicateHash(_hashHandle))
fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination))
{
hashHandle.Dispose();
throw Interop.BCrypt.CreateCryptographicException(ntStatus);
NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(tmpHash, pDestination, destination.Length, dwFlags: 0);

if (ntStatus != NTSTATUS.STATUS_SUCCESS)
{
throw Interop.BCrypt.CreateCryptographicException(ntStatus);
}
}
}

_hashHandle = hashHandle;
public LiteXof Clone()
{
SafeBCryptHashHandle clone = Interop.BCrypt.BCryptDuplicateHash(_hashHandle);
return new LiteXof(clone, _algorithm);
}

public readonly unsafe void Current(Span<byte> destination)
public unsafe void Read(Span<byte> destination)
{
using (SafeBCryptHashHandle tmpHash = Interop.BCrypt.BCryptDuplicateHash(_hashHandle))
fixed (byte* pDestination = &Helpers.GetNonNullPinnableReference(destination))
{
NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(tmpHash, pDestination, destination.Length, dwFlags: 0);
NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hashHandle, pDestination, destination.Length, dwFlags: BCRYPT_HASH_DONT_RESET_FLAG);

if (ntStatus != NTSTATUS.STATUS_SUCCESS)
{
Expand All @@ -259,7 +280,7 @@ public readonly unsafe void Current(Span<byte> destination)
}
}

public readonly void Dispose()
public void Dispose()
{
_hashHandle.Dispose();
}
Expand Down
Loading

0 comments on commit ef465c1

Please sign in to comment.