Skip to content

Commit 20b4e85

Browse files
ML-DSA BCrypt
1 parent 8091e60 commit 20b4e85

26 files changed

+566
-56
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ internal static class AlgorithmName
3131
public const string ECDsaP521 = "ECDSA_P521"; // BCRYPT_ECDSA_P521_ALGORITHM
3232
public const string RSA = "RSA"; // BCRYPT_RSA_ALGORITHM
3333
public const string MD5 = "MD5"; // BCRYPT_MD5_ALGORITHM
34+
public const string MLDsa = "ML-DSA"; // BCRYPT_MLDSA_ALGORITHM
3435
public const string Sha1 = "SHA1"; // BCRYPT_SHA1_ALGORITHM
3536
public const string Sha256 = "SHA256"; // BCRYPT_SHA256_ALGORITHM
3637
public const string Sha384 = "SHA384"; // BCRYPT_SHA384_ALGORITHM

src/libraries/Common/src/Interop/Windows/BCrypt/Interop.AsymmetricEncryption.Types.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,24 @@ internal struct BCRYPT_PSS_PADDING_INFO
5353
/// </summary>
5454
internal int cbSalt;
5555
}
56+
57+
[StructLayout(LayoutKind.Sequential)]
58+
internal struct BCRYPT_PQDSA_PADDING_INFO
59+
{
60+
/// <summary>
61+
/// Address of the context buffer.
62+
/// </summary>
63+
internal IntPtr pbCtx;
64+
65+
/// <summary>
66+
/// The size, in bytes, of the context buffer.
67+
/// </summary>
68+
internal int cbCtx;
69+
70+
/// <summary>
71+
/// Null-terminated Unicode string that identifies the pre-hash algorithm used to create the hash.
72+
/// </summary>
73+
internal IntPtr pszPreHashAlgId;
74+
}
5675
}
5776
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ private static unsafe partial NTSTATUS BCryptGenerateKeyPair(
1818

1919
internal static SafeBCryptKeyHandle BCryptGenerateKeyPair(
2020
SafeBCryptAlgorithmHandle hAlgorithm,
21-
int keyLength)
21+
int keyLength = 0)
2222
{
2323
NTSTATUS status = BCryptGenerateKeyPair(
2424
hAlgorithm,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ internal static class BCryptPropertyStrings
1313
internal const string BCRYPT_HASH_LENGTH = "HashDigestLength";
1414
internal const string BCRYPT_KEY_STRENGTH = "KeyStrength";
1515
internal const string BCRYPT_MESSAGE_BLOCK_LENGTH = "MessageBlockLength";
16+
internal const string BCRYPT_PARAMETER_SET_NAME = "ParameterSetName";
1617
}
1718
}
1819
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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.Runtime.InteropServices;
5+
6+
using Microsoft.Win32.SafeHandles;
7+
8+
internal static partial class Interop
9+
{
10+
internal static partial class BCrypt
11+
{
12+
[LibraryImport(Libraries.BCrypt, StringMarshalling = StringMarshalling.Utf16)]
13+
internal static unsafe partial NTSTATUS BCryptSetProperty(
14+
SafeBCryptHandle hObject,
15+
string pszProperty,
16+
void* pbInput,
17+
int cbInput,
18+
int dwFlags);
19+
20+
internal static unsafe void BCryptSetSZProperty(SafeBCryptHandle hObject, string pszProperty, string pszValue)
21+
{
22+
fixed (void* pbInput = pszValue)
23+
{
24+
NTSTATUS status = BCryptSetProperty(
25+
hObject,
26+
pszProperty,
27+
pbInput,
28+
(pszValue.Length + 1) * 2,
29+
0);
30+
31+
if (status != NTSTATUS.STATUS_SUCCESS)
32+
{
33+
throw CreateCryptographicException(status);
34+
}
35+
}
36+
}
37+
}
38+
}

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5+
using System.Diagnostics;
56
using System.Runtime.InteropServices;
67
using Internal.Cryptography;
78

@@ -74,5 +75,58 @@ internal static unsafe NTSTATUS BCryptSignHashPss(
7475
BCryptSignVerifyFlags.BCRYPT_PAD_PSS);
7576
}
7677
}
78+
79+
internal static unsafe void BCryptSignHashPure(
80+
SafeBCryptKeyHandle key,
81+
ReadOnlySpan<byte> data,
82+
ReadOnlySpan<byte> context,
83+
Span<byte> destination)
84+
{
85+
NTSTATUS status;
86+
int bytesWritten;
87+
88+
fixed (byte* pData = &MemoryMarshal.GetReference(data))
89+
fixed (byte* pDest = &Helpers.GetNonNullPinnableReference(destination))
90+
{
91+
if (context.Length == 0)
92+
{
93+
status = BCryptSignHash(
94+
key,
95+
pPaddingInfo: null,
96+
pData,
97+
data.Length,
98+
pDest,
99+
destination.Length,
100+
out bytesWritten,
101+
default(BCryptSignVerifyFlags));
102+
}
103+
else
104+
{
105+
fixed (byte* pContext = &MemoryMarshal.GetReference(context))
106+
{
107+
BCRYPT_PQDSA_PADDING_INFO paddingInfo = default;
108+
paddingInfo.pbCtx = (IntPtr)pContext;
109+
paddingInfo.cbCtx = context.Length;
110+
111+
status = BCryptSignHash(
112+
key,
113+
&paddingInfo,
114+
pData,
115+
data.Length,
116+
pDest,
117+
destination.Length,
118+
out bytesWritten,
119+
BCryptSignVerifyFlags.BCRYPT_PAD_PQDSA);
120+
}
121+
}
122+
}
123+
124+
Debug.Assert(bytesWritten == destination.Length);
125+
126+
if (status != Interop.BCrypt.NTSTATUS.STATUS_SUCCESS)
127+
{
128+
throw Interop.BCrypt.CreateCryptographicException(status);
129+
}
130+
}
77131
}
78132
}

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Runtime.InteropServices;
66

7+
using Internal.Cryptography;
78
using Microsoft.Win32.SafeHandles;
89

910
internal static partial class Interop
@@ -15,6 +16,7 @@ private enum BCryptSignVerifyFlags : uint
1516
{
1617
BCRYPT_PAD_PKCS1 = 2,
1718
BCRYPT_PAD_PSS = 8,
19+
BCRYPT_PAD_PQDSA = 32,
1820
}
1921

2022
[LibraryImport(Libraries.BCrypt)]
@@ -84,5 +86,50 @@ internal static unsafe bool BCryptVerifySignaturePss(
8486

8587
return status == NTSTATUS.STATUS_SUCCESS;
8688
}
89+
90+
internal static unsafe bool BCryptVerifySignaturePure(
91+
SafeBCryptKeyHandle key,
92+
ReadOnlySpan<byte> data,
93+
ReadOnlySpan<byte> context,
94+
ReadOnlySpan<byte> signature)
95+
{
96+
NTSTATUS status;
97+
98+
fixed (byte* pData = &Helpers.GetNonNullPinnableReference(data))
99+
fixed (byte* pSignature = &MemoryMarshal.GetReference(signature))
100+
{
101+
if (context.Length == 0)
102+
{
103+
status = BCryptVerifySignature(
104+
key,
105+
pPaddingInfo: null,
106+
pData,
107+
data.Length,
108+
pSignature,
109+
signature.Length,
110+
default(BCryptSignVerifyFlags));
111+
}
112+
else
113+
{
114+
fixed (byte* pContext = &MemoryMarshal.GetReference(context))
115+
{
116+
BCRYPT_PQDSA_PADDING_INFO paddingInfo = default;
117+
paddingInfo.pbCtx = (IntPtr)pContext;
118+
paddingInfo.cbCtx = context.Length;
119+
120+
status = BCryptVerifySignature(
121+
key,
122+
&paddingInfo,
123+
pData,
124+
data.Length,
125+
pSignature,
126+
signature.Length,
127+
BCryptSignVerifyFlags.BCRYPT_PAD_PQDSA);
128+
}
129+
}
130+
}
131+
132+
return status == NTSTATUS.STATUS_SUCCESS;
133+
}
87134
}
88135
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ internal enum KeyBlobMagicNumber : int
106106
BCRYPT_ECDSA_PUBLIC_GENERIC_MAGIC = 0x50444345,
107107
BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC = 0x56444345,
108108

109+
BCRYPT_MLDSA_PUBLIC_MAGIC = 0x4B505344,
110+
BCRYPT_MLDSA_PRIVATE_MAGIC = 0x4B535344,
111+
BCRYPT_MLDSA_PRIVATE_SEED_MAGIC = 0x53535344,
112+
109113
BCRYPT_RSAPUBLIC_MAGIC = 0x31415352,
110114
BCRYPT_RSAPRIVATE_MAGIC = 0x32415352,
111115
BCRYPT_RSAFULLPRIVATE_MAGIC = 0x33415352,
@@ -133,6 +137,10 @@ internal static class KeyBlobType
133137
internal const string BCRYPT_ECCPRIVATE_BLOB = "ECCPRIVATEBLOB";
134138
internal const string BCRYPT_ECCFULLPUBLIC_BLOB = "ECCFULLPUBLICBLOB";
135139
internal const string BCRYPT_ECCFULLPRIVATE_BLOB = "ECCFULLPRIVATEBLOB";
140+
141+
internal const string BCRYPT_PQDSA_PUBLIC_BLOB = "PQDSAPUBLICBLOB";
142+
internal const string BCRYPT_PQDSA_PRIVATE_BLOB = "PQDSAPRIVATEBLOB";
143+
internal const string BCRYPT_PQDSA_PRIVATE_SEED_BLOB = "PQDSAPRIVATESEEDBLOB";
136144
}
137145

138146
/// <summary>
@@ -235,6 +243,18 @@ internal struct BCRYPT_ECCFULLKEY_BLOB
235243
// The rest of the buffer contains the domain parameters
236244
}
237245

246+
/// <summary>
247+
/// Used as a header to PQC parameters including the parameters set and key/seed.
248+
/// </summary>
249+
[StructLayout(LayoutKind.Sequential)]
250+
internal struct BCRYPT_PQDSA_KEY_BLOB
251+
{
252+
internal KeyBlobMagicNumber Magic;
253+
internal int cbParameterSet; // Byte size of parameterSet[]
254+
internal int cbKey; // Byte size of key[]
255+
// The rest of the buffer contains the data
256+
}
257+
238258
/// <summary>
239259
/// NCrypt or BCrypt buffer descriptors
240260
/// </summary>

src/libraries/Common/src/System/Security/Cryptography/MLDsaImplementation.NotSupported.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ namespace System.Security.Cryptography
88
{
99
internal sealed partial class MLDsaImplementation : MLDsa
1010
{
11+
public MLDsaImplementation(MLDsaAlgorithm algorithm)
12+
: base(algorithm)
13+
{
14+
ThrowIfNotSupported();
15+
}
16+
1117
internal static partial bool SupportsAny() => false;
1218

1319
// The instance override methods are unreachable, as the constructor will always throw.
@@ -35,9 +41,6 @@ internal static partial MLDsaImplementation GenerateKeyImpl(MLDsaAlgorithm algor
3541
internal static partial MLDsaImplementation ImportPublicKey(MLDsaAlgorithm algorithm, ReadOnlySpan<byte> source) =>
3642
throw new PlatformNotSupportedException();
3743

38-
internal static partial MLDsaImplementation ImportPkcs8PrivateKeyValue(MLDsaAlgorithm algorithm, ReadOnlySpan<byte> source) =>
39-
throw new PlatformNotSupportedException();
40-
4144
internal static partial MLDsaImplementation ImportSecretKey(MLDsaAlgorithm algorithm, ReadOnlySpan<byte> source) =>
4245
throw new PlatformNotSupportedException();
4346

0 commit comments

Comments
 (0)