Skip to content

Commit

Permalink
Implement KMAC
Browse files Browse the repository at this point in the history
  • Loading branch information
vcsjones committed Jan 11, 2024
1 parent 8d1c3d9 commit 7d5aeed
Show file tree
Hide file tree
Showing 38 changed files with 6,680 additions and 173 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,6 @@ 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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class Crypto
{
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacFree")]
internal static partial void EvpMacFree(IntPtr mac);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacCtxFree")]
internal static partial void EvpMacCtxFree(IntPtr ctx);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacCtxNew")]
private static partial SafeEvpMacCtxHandle CryptoNative_EvpMacCtxNew(SafeEvpMacHandle mac);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacInit")]
private static partial int CryptoNative_EvpMacInit(
SafeEvpMacCtxHandle ctx,
ReadOnlySpan<byte> key,
int keyLength,
ReadOnlySpan<byte> customizationString,
int customizationStringLength,
[MarshalAs(UnmanagedType.Bool)] bool xof);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacUpdate")]
private static partial int CryptoNative_EvpMacUpdate(SafeEvpMacCtxHandle ctx, ReadOnlySpan<byte> data, int dataLength);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacFinal")]
private static partial int CryptoNative_EvpMacFinal(SafeEvpMacCtxHandle ctx, Span<byte> mac, int macLength);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacReset")]
private static partial int CryptoNative_EvpMacReset(SafeEvpMacCtxHandle ctx);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacCurrent")]
private static partial int CryptoNative_EvpMacCurrent(SafeEvpMacCtxHandle ctx, Span<byte> mac, int macLength);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacOneShot", StringMarshalling = StringMarshalling.Utf8)]
private static partial int CryptoNative_EvpMacOneShot(
SafeEvpMacHandle mac,
ReadOnlySpan<byte> key,
int keyLength,
ReadOnlySpan<byte> customizationString,
int customizationStringLength,
ReadOnlySpan<byte> data,
int dataLength,
Span<byte> destination,
int destinationLength,
[MarshalAs(UnmanagedType.Bool)] bool xof);

internal static void EvpMacOneShot(
SafeEvpMacHandle mac,
ReadOnlySpan<byte> key,
ReadOnlySpan<byte> customizationString,
ReadOnlySpan<byte> data,
Span<byte> destination,
bool xof)
{
const int Success = 1;

int ret = CryptoNative_EvpMacOneShot(
mac,
key,
key.Length,
customizationString,
customizationString.Length,
data,
data.Length,
destination,
destination.Length,
xof);

if (ret != Success)
{
Debug.Assert(ret == 0);
throw CreateOpenSslCryptographicException();
}
}

internal static void EvpMacFinal(SafeEvpMacCtxHandle ctx, Span<byte> mac)
{
int ret = CryptoNative_EvpMacFinal(ctx, mac, mac.Length);
const int Success = 1;

if (ret != Success)
{
Debug.Assert(ret == 0);
throw CreateOpenSslCryptographicException();
}
}

internal static void EvpMacCurrent(SafeEvpMacCtxHandle ctx, Span<byte> mac)
{
int ret = CryptoNative_EvpMacCurrent(ctx, mac, mac.Length);
const int Success = 1;

if (ret != Success)
{
Debug.Assert(ret == 0);
throw CreateOpenSslCryptographicException();
}
}

internal static SafeEvpMacCtxHandle EvpMacCtxNew(SafeEvpMacHandle mac)
{
SafeEvpMacCtxHandle ctx = CryptoNative_EvpMacCtxNew(mac);

if (ctx.IsInvalid)
{
ctx.Dispose();
throw CreateOpenSslCryptographicException();
}

return ctx;
}

internal static void EvpMacInit(
SafeEvpMacCtxHandle ctx,
ReadOnlySpan<byte> key,
ReadOnlySpan<byte> customizationString,
bool xof)
{
int ret = CryptoNative_EvpMacInit(ctx, key, key.Length, customizationString, customizationString.Length, xof);
const int Success = 1;

if (ret != Success)
{
Debug.Assert(ret == 0);
throw CreateOpenSslCryptographicException();
}
}

internal static void EvpMacUpdate(SafeEvpMacCtxHandle ctx, ReadOnlySpan<byte> data)
{
int ret = CryptoNative_EvpMacUpdate(ctx, data, data.Length);
const int Success = 1;

if (ret != Success)
{
Debug.Assert(ret == 0);
throw CreateOpenSslCryptographicException();
}
}

internal static void EvpMacReset(SafeEvpMacCtxHandle ctx)
{
int ret = CryptoNative_EvpMacReset(ctx);
const int Success = 1;

if (ret != Success)
{
Debug.Assert(ret == 0);
throw CreateOpenSslCryptographicException();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class Crypto
{
internal static partial class EvpMacAlgs
{
internal static SafeEvpMacHandle? Kmac128 { get; } = EvpMacFetch(HashAlgorithmNames.KMAC128);
internal static SafeEvpMacHandle? Kmac256 { get; } = EvpMacFetch(HashAlgorithmNames.KMAC256);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacFetch", StringMarshalling = StringMarshalling.Utf8)]
private static partial SafeEvpMacHandle CryptoNative_EvpMacFetch(string algorithm, out int haveFeature);

private static SafeEvpMacHandle? EvpMacFetch(string algorithm)
{
SafeEvpMacHandle mac = CryptoNative_EvpMacFetch(algorithm, out int haveFeature);

if (haveFeature == 0)
{
Debug.Assert(mac.IsInvalid);
mac.Dispose();
return null;
}

if (mac.IsInvalid)
{
mac.Dispose();
throw CreateOpenSslCryptographicException();
}

return mac;
}
}
}
}
3 changes: 3 additions & 0 deletions src/libraries/Common/src/Interop/Windows/BCrypt/Cng.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ internal static partial class Interop
[LibraryImport(Libraries.BCrypt, EntryPoint = "BCryptSetProperty", StringMarshalling = StringMarshalling.Utf16)]
private static partial NTSTATUS BCryptSetIntPropertyPrivate(SafeBCryptHandle hObject, string pszProperty, ref int pdwInput, int cbInput, int dwFlags);

[LibraryImport(Libraries.BCrypt, StringMarshalling = StringMarshalling.Utf16)]
public static partial NTSTATUS BCryptSetProperty(SafeBCryptHandle hObject, string pszProperty, ReadOnlySpan<byte> pbInput, int cbInput, int dwFlags);

public static unsafe NTSTATUS BCryptSetIntProperty(SafeBCryptHandle hObject, string pszProperty, ref int pdwInput, int dwFlags)
{
return BCryptSetIntPropertyPrivate(hObject, pszProperty, ref pdwInput, sizeof(int), dwFlags);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public enum BCryptAlgPseudoHandle : uint
BCRYPT_HMAC_SHA3_512_ALG_HANDLE = 0x00000401,
BCRYPT_CSHAKE128_ALG_HANDLE = 0x00000411,
BCRYPT_CSHAKE256_ALG_HANDLE = 0x00000421,
BCRYPT_KMAC128_ALG_HANDLE = 0x00000431,
BCRYPT_KMAC256_ALG_HANDLE = 0x00000441,
}

internal static bool PseudoHandlesSupported { get; } =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Security;
using System.Runtime.InteropServices;

namespace Microsoft.Win32.SafeHandles
{
internal sealed class SafeEvpMacCtxHandle : SafeHandle
{
public SafeEvpMacCtxHandle() : base(0, ownsHandle: true)
{
}

protected override bool ReleaseHandle()
{
Interop.Crypto.EvpMacCtxFree(handle);
return true;
}

public override bool IsInvalid => handle == 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Security;
using System.Runtime.InteropServices;

namespace Microsoft.Win32.SafeHandles
{
internal sealed class SafeEvpMacHandle : SafeHandle
{
public SafeEvpMacHandle() : base(0, ownsHandle: true)
{
}

protected override bool ReleaseHandle()
{
Interop.Crypto.EvpMacFree(handle);
return true;
}

public override bool IsInvalid => handle == 0;
}
}
Loading

0 comments on commit 7d5aeed

Please sign in to comment.