Skip to content

Commit 8b5e033

Browse files
committed
Implement KMAC.
1 parent acc3f0c commit 8b5e033

37 files changed

+6279
-173
lines changed

src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs

-10
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,6 @@ internal static partial class Crypto
3838
[LibraryImport(Libraries.AndroidCryptoNative, EntryPoint = "CryptoNative_GetMaxMdSize")]
3939
private static partial int GetMaxMdSize();
4040

41-
internal static unsafe int EvpDigestXOFOneShot(IntPtr type, ReadOnlySpan<byte> source, Span<byte> destination)
42-
{
43-
// The partial needs to match the OpenSSL parameters.
44-
_ = type;
45-
_ = source;
46-
_ = destination;
47-
Debug.Fail("Should have validated that XOF is not supported before getting here.");
48-
throw new UnreachableException();
49-
}
50-
5141
internal static unsafe int EvpDigestFinalXOF(SafeEvpMdCtxHandle ctx, Span<byte> destination)
5242
{
5343
// The partial needs to match the OpenSSL parameters.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Runtime.InteropServices;
7+
using Microsoft.Win32.SafeHandles;
8+
9+
internal static partial class Interop
10+
{
11+
internal static partial class Crypto
12+
{
13+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacFree")]
14+
internal static partial void EvpMacFree(IntPtr mac);
15+
16+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacCtxFree")]
17+
internal static partial void EvpMacCtxFree(IntPtr ctx);
18+
19+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacCtxNew")]
20+
private static partial SafeEvpMacCtxHandle CryptoNative_EvpMacCtxNew(SafeEvpMacHandle mac);
21+
22+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacInit")]
23+
private static partial int CryptoNative_EvpMacInit(
24+
SafeEvpMacCtxHandle ctx,
25+
ReadOnlySpan<byte> key,
26+
int keyLength,
27+
ReadOnlySpan<byte> customizationString,
28+
int customizationStringLength,
29+
[MarshalAs(UnmanagedType.Bool)] bool xof);
30+
31+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacUpdate")]
32+
private static partial int CryptoNative_EvpMacUpdate(SafeEvpMacCtxHandle ctx, ReadOnlySpan<byte> data, int dataLength);
33+
34+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacFinal")]
35+
private static partial int CryptoNative_EvpMacFinal(SafeEvpMacCtxHandle ctx, Span<byte> mac, int macLength);
36+
37+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacReset")]
38+
private static partial int CryptoNative_EvpMacReset(SafeEvpMacCtxHandle ctx);
39+
40+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacCurrent")]
41+
private static partial int CryptoNative_EvpMacCurrent(SafeEvpMacCtxHandle ctx, Span<byte> mac, int macLength);
42+
43+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacOneShot", StringMarshalling = StringMarshalling.Utf8)]
44+
private static partial int CryptoNative_EvpMacOneShot(
45+
SafeEvpMacHandle mac,
46+
ReadOnlySpan<byte> key,
47+
int keyLength,
48+
ReadOnlySpan<byte> customizationString,
49+
int customizationStringLength,
50+
ReadOnlySpan<byte> data,
51+
int dataLength,
52+
Span<byte> destination,
53+
int destinationLength,
54+
[MarshalAs(UnmanagedType.Bool)] bool xof);
55+
56+
internal static void EvpMacOneShot(
57+
SafeEvpMacHandle mac,
58+
ReadOnlySpan<byte> key,
59+
ReadOnlySpan<byte> customizationString,
60+
ReadOnlySpan<byte> data,
61+
Span<byte> destination,
62+
bool xof)
63+
{
64+
const int Success = 1;
65+
66+
int ret = CryptoNative_EvpMacOneShot(
67+
mac,
68+
key,
69+
key.Length,
70+
customizationString,
71+
customizationString.Length,
72+
data,
73+
data.Length,
74+
destination,
75+
destination.Length,
76+
xof);
77+
78+
if (ret != Success)
79+
{
80+
Debug.Assert(ret == 0);
81+
throw CreateOpenSslCryptographicException();
82+
}
83+
}
84+
85+
internal static void EvpMacFinal(SafeEvpMacCtxHandle ctx, Span<byte> mac)
86+
{
87+
int ret = CryptoNative_EvpMacFinal(ctx, mac, mac.Length);
88+
const int Success = 1;
89+
90+
if (ret != Success)
91+
{
92+
Debug.Assert(ret == 0);
93+
throw CreateOpenSslCryptographicException();
94+
}
95+
}
96+
97+
internal static void EvpMacCurrent(SafeEvpMacCtxHandle ctx, Span<byte> mac)
98+
{
99+
int ret = CryptoNative_EvpMacCurrent(ctx, mac, mac.Length);
100+
const int Success = 1;
101+
102+
if (ret != Success)
103+
{
104+
Debug.Assert(ret == 0);
105+
throw CreateOpenSslCryptographicException();
106+
}
107+
}
108+
109+
internal static SafeEvpMacCtxHandle EvpMacCtxNew(SafeEvpMacHandle mac)
110+
{
111+
SafeEvpMacCtxHandle ctx = CryptoNative_EvpMacCtxNew(mac);
112+
113+
if (ctx.IsInvalid)
114+
{
115+
ctx.Dispose();
116+
throw CreateOpenSslCryptographicException();
117+
}
118+
119+
return ctx;
120+
}
121+
122+
internal static void EvpMacInit(
123+
SafeEvpMacCtxHandle ctx,
124+
ReadOnlySpan<byte> key,
125+
ReadOnlySpan<byte> customizationString,
126+
bool xof)
127+
{
128+
int ret = CryptoNative_EvpMacInit(ctx, key, key.Length, customizationString, customizationString.Length, xof);
129+
const int Success = 1;
130+
131+
if (ret != Success)
132+
{
133+
Debug.Assert(ret == 0);
134+
throw CreateOpenSslCryptographicException();
135+
}
136+
}
137+
138+
internal static void EvpMacUpdate(SafeEvpMacCtxHandle ctx, ReadOnlySpan<byte> data)
139+
{
140+
int ret = CryptoNative_EvpMacUpdate(ctx, data, data.Length);
141+
const int Success = 1;
142+
143+
if (ret != Success)
144+
{
145+
Debug.Assert(ret == 0);
146+
throw CreateOpenSslCryptographicException();
147+
}
148+
}
149+
150+
internal static void EvpMacReset(SafeEvpMacCtxHandle ctx)
151+
{
152+
int ret = CryptoNative_EvpMacReset(ctx);
153+
const int Success = 1;
154+
155+
if (ret != Success)
156+
{
157+
Debug.Assert(ret == 0);
158+
throw CreateOpenSslCryptographicException();
159+
}
160+
}
161+
}
162+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics;
5+
using System.Runtime.InteropServices;
6+
using System.Security.Cryptography;
7+
using Microsoft.Win32.SafeHandles;
8+
9+
internal static partial class Interop
10+
{
11+
internal static partial class Crypto
12+
{
13+
internal static partial class EvpMacAlgs
14+
{
15+
internal static SafeEvpMacHandle? Kmac128 { get; } = EvpMacFetch(HashAlgorithmNames.KMAC128);
16+
internal static SafeEvpMacHandle? Kmac256 { get; } = EvpMacFetch(HashAlgorithmNames.KMAC256);
17+
18+
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMacFetch", StringMarshalling = StringMarshalling.Utf8)]
19+
private static partial SafeEvpMacHandle CryptoNative_EvpMacFetch(string algorithm, out int haveFeature);
20+
21+
private static SafeEvpMacHandle? EvpMacFetch(string algorithm)
22+
{
23+
SafeEvpMacHandle mac = CryptoNative_EvpMacFetch(algorithm, out int haveFeature);
24+
25+
if (haveFeature == 0)
26+
{
27+
Debug.Assert(mac.IsInvalid);
28+
mac.Dispose();
29+
return null;
30+
}
31+
32+
if (mac.IsInvalid)
33+
{
34+
mac.Dispose();
35+
throw CreateOpenSslCryptographicException();
36+
}
37+
38+
return mac;
39+
}
40+
}
41+
}
42+
}

src/libraries/Common/src/Interop/Windows/BCrypt/Cng.cs

+3
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ internal static partial class Interop
134134
[LibraryImport(Libraries.BCrypt, EntryPoint = "BCryptSetProperty", StringMarshalling = StringMarshalling.Utf16)]
135135
private static partial NTSTATUS BCryptSetIntPropertyPrivate(SafeBCryptHandle hObject, string pszProperty, ref int pdwInput, int cbInput, int dwFlags);
136136

137+
[LibraryImport(Libraries.BCrypt, StringMarshalling = StringMarshalling.Utf16)]
138+
public static partial NTSTATUS BCryptSetProperty(SafeBCryptHandle hObject, string pszProperty, ReadOnlySpan<byte> pbInput, int cbInput, int dwFlags);
139+
137140
public static unsafe NTSTATUS BCryptSetIntProperty(SafeBCryptHandle hObject, string pszProperty, ref int pdwInput, int dwFlags)
138141
{
139142
return BCryptSetIntPropertyPrivate(hObject, pszProperty, ref pdwInput, sizeof(int), dwFlags);

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptAlgPseudoHandle.cs

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public enum BCryptAlgPseudoHandle : uint
3131
BCRYPT_HMAC_SHA3_512_ALG_HANDLE = 0x00000401,
3232
BCRYPT_CSHAKE128_ALG_HANDLE = 0x00000411,
3333
BCRYPT_CSHAKE256_ALG_HANDLE = 0x00000421,
34+
BCRYPT_KMAC128_ALG_HANDLE = 0x00000431,
35+
BCRYPT_KMAC256_ALG_HANDLE = 0x00000441,
3436
}
3537

3638
internal static bool PseudoHandlesSupported { get; } =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Security;
6+
using System.Runtime.InteropServices;
7+
8+
namespace Microsoft.Win32.SafeHandles
9+
{
10+
internal sealed class SafeEvpMacCtxHandle : SafeHandle
11+
{
12+
public SafeEvpMacCtxHandle() : base(0, ownsHandle: true)
13+
{
14+
}
15+
16+
protected override bool ReleaseHandle()
17+
{
18+
Interop.Crypto.EvpMacCtxFree(handle);
19+
return true;
20+
}
21+
22+
public override bool IsInvalid => handle == 0;
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Security;
6+
using System.Runtime.InteropServices;
7+
8+
namespace Microsoft.Win32.SafeHandles
9+
{
10+
internal sealed class SafeEvpMacHandle : SafeHandle
11+
{
12+
public SafeEvpMacHandle() : base(0, ownsHandle: true)
13+
{
14+
}
15+
16+
protected override bool ReleaseHandle()
17+
{
18+
Interop.Crypto.EvpMacFree(handle);
19+
return true;
20+
}
21+
22+
public override bool IsInvalid => handle == 0;
23+
}
24+
}

0 commit comments

Comments
 (0)