Skip to content

Commit fe45871

Browse files
vcsjonesCopilot
andauthored
Implement X25519DiffieHellmanCng
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 231343a commit fe45871

17 files changed

Lines changed: 976 additions & 214 deletions

src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ internal static partial class NCrypt
3131
[LibraryImport(Interop.Libraries.NCrypt, StringMarshalling = StringMarshalling.Utf16)]
3232
internal static partial ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, ref byte pbOutput, int cbOutput, out int pcbResult, int dwFlags);
3333

34+
[LibraryImport(Interop.Libraries.NCrypt, StringMarshalling = StringMarshalling.Utf16)]
35+
internal static partial ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, Span<byte> pbOutput, int cbOutput, out int pcbResult, int dwFlags);
36+
3437
[LibraryImport(Interop.Libraries.NCrypt, StringMarshalling = StringMarshalling.Utf16)]
3538
internal static partial ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, ref NCryptBufferDesc pParameterList, ref byte pbOutput, int cbOutput, out int pcbResult, int dwFlags);
3639

src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveKeyMaterial.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ private static partial ErrorCode NCryptDeriveKey(
2525
out int pcbResult,
2626
SecretAgreementFlags dwFlags);
2727

28+
[LibraryImport(Interop.Libraries.NCrypt, StringMarshalling = StringMarshalling.Utf16)]
29+
private static partial ErrorCode NCryptDeriveKey(
30+
SafeNCryptSecretHandle hSharedSecret,
31+
string pwszKDF,
32+
IntPtr pParameterList,
33+
Span<byte> pbDerivedKey,
34+
int cbDerivedKey,
35+
out int pcbResult,
36+
SecretAgreementFlags dwFlags);
37+
2838
/// <summary>
2939
/// Derive key material from a hash or HMAC KDF
3040
/// </summary>
@@ -257,5 +267,35 @@ internal static byte[] DeriveKeyMaterialTruncate(
257267
Array.Reverse(result);
258268
return result;
259269
}
270+
271+
internal static bool TryDeriveKeyMaterialTruncate(
272+
SafeNCryptSecretHandle secretAgreement,
273+
SecretAgreementFlags flags,
274+
Span<byte> destination,
275+
out int bytesWritten)
276+
{
277+
ErrorCode error = NCryptDeriveKey(
278+
secretAgreement,
279+
BCryptNative.KeyDerivationFunction.Raw,
280+
IntPtr.Zero,
281+
destination,
282+
destination.Length,
283+
out int localWritten,
284+
flags);
285+
286+
switch (error)
287+
{
288+
case ErrorCode.ERROR_SUCCESS:
289+
destination.Slice(0, localWritten).Reverse();
290+
bytesWritten = localWritten;
291+
return true;
292+
case ErrorCode c when c.IsBufferTooSmall():
293+
destination.Clear();
294+
bytesWritten = 0;
295+
return false;
296+
default:
297+
throw error.ToCryptographicException();
298+
}
299+
}
260300
}
261301
}

src/libraries/Common/src/System/Security/Cryptography/ECCng.ImportExport.NamedCurve.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ internal static SafeNCryptKeyHandle ImportKeyBlob(
145145
string blobType,
146146
ReadOnlySpan<byte> keyBlob,
147147
string curveName,
148-
SafeNCryptProviderHandle provider)
148+
SafeNCryptProviderHandle provider,
149+
int flags = 0)
149150
{
150151
ErrorCode errorCode;
151152
SafeNCryptKeyHandle keyHandle;
@@ -173,7 +174,7 @@ internal static SafeNCryptKeyHandle ImportKeyBlob(
173174
out keyHandle,
174175
ref MemoryMarshal.GetReference(keyBlob),
175176
keyBlob.Length,
176-
0);
177+
flags);
177178
}
178179
}
179180

src/libraries/Common/src/System/Security/Cryptography/KeyFormatHelper.Encrypted.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,29 @@ internal static void ReadEncryptedPkcs8<TRet>(
3232
out ret);
3333
}
3434

35+
internal static void ReadEncryptedPkcs8<TRet, TState>(
36+
string[] validOids,
37+
ReadOnlySpan<byte> source,
38+
ReadOnlySpan<char> password,
39+
TState state,
40+
KeyReader<TRet, TState> keyReader,
41+
out int bytesRead,
42+
out TRet ret)
43+
#if NET
44+
where TState : allows ref struct
45+
#endif
46+
{
47+
ReadEncryptedPkcs8(
48+
validOids,
49+
source,
50+
password,
51+
ReadOnlySpan<byte>.Empty,
52+
state,
53+
keyReader,
54+
out bytesRead,
55+
out ret);
56+
}
57+
3558
internal static void ReadEncryptedPkcs8<TRet>(
3659
string[] validOids,
3760
ReadOnlySpan<byte> source,
@@ -50,6 +73,29 @@ internal static void ReadEncryptedPkcs8<TRet>(
5073
out ret);
5174
}
5275

76+
internal static void ReadEncryptedPkcs8<TRet, TState>(
77+
string[] validOids,
78+
ReadOnlySpan<byte> source,
79+
ReadOnlySpan<byte> passwordBytes,
80+
TState state,
81+
KeyReader<TRet, TState> keyReader,
82+
out int bytesRead,
83+
out TRet ret)
84+
#if NET
85+
where TState : allows ref struct
86+
#endif
87+
{
88+
ReadEncryptedPkcs8(
89+
validOids,
90+
source,
91+
ReadOnlySpan<char>.Empty,
92+
passwordBytes,
93+
state,
94+
keyReader,
95+
out bytesRead,
96+
out ret);
97+
}
98+
5399
private static void ReadEncryptedPkcs8<TRet>(
54100
string[] validOids,
55101
ReadOnlySpan<byte> source,
@@ -58,6 +104,30 @@ private static void ReadEncryptedPkcs8<TRet>(
58104
KeyReader<TRet> keyReader,
59105
out int bytesRead,
60106
out TRet ret)
107+
{
108+
ReadEncryptedPkcs8<TRet, KeyReader<TRet>>(
109+
validOids,
110+
source,
111+
password,
112+
passwordBytes,
113+
keyReader,
114+
static (key, kr, in algId, out ret) => kr(key, algId, out ret),
115+
out bytesRead,
116+
out ret);
117+
}
118+
119+
private static void ReadEncryptedPkcs8<TRet, TState>(
120+
string[] validOids,
121+
ReadOnlySpan<byte> source,
122+
ReadOnlySpan<char> password,
123+
ReadOnlySpan<byte> passwordBytes,
124+
TState state,
125+
KeyReader<TRet, TState> keyReader,
126+
out int bytesRead,
127+
out TRet ret)
128+
#if NET
129+
where TState : allows ref struct
130+
#endif
61131
{
62132
int read;
63133
ValueEncryptedPrivateKeyInfoAsn epki;
@@ -92,6 +162,7 @@ private static void ReadEncryptedPkcs8<TRet>(
92162
ReadPkcs8(
93163
validOids,
94164
decryptedMemory.Span,
165+
state,
95166
keyReader,
96167
out int innerRead,
97168
out ret);

src/libraries/Common/src/System/Security/Cryptography/KeyFormatHelper.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ internal static partial class KeyFormatHelper
1313
{
1414
internal delegate void KeyReader<TRet>(ReadOnlySpan<byte> key, in ValueAlgorithmIdentifierAsn algId, out TRet ret);
1515

16+
internal delegate void KeyReader<TRet, TState>(ReadOnlySpan<byte> key, TState state, in ValueAlgorithmIdentifierAsn algId, out TRet ret)
17+
#if NET
18+
where TState : allows ref struct;
19+
#else
20+
;
21+
#endif
22+
1623
internal static void ReadSubjectPublicKeyInfo<TRet>(
1724
string[] validOids,
1825
ReadOnlySpan<byte> source,
@@ -78,6 +85,26 @@ internal static void ReadPkcs8<TRet>(
7885
KeyReader<TRet> keyReader,
7986
out int bytesRead,
8087
out TRet ret)
88+
{
89+
ReadPkcs8<TRet, KeyReader<TRet>>(
90+
validOids,
91+
source,
92+
keyReader,
93+
static (key, kr, in algId, out ret) => kr(key, algId, out ret),
94+
out bytesRead,
95+
out ret);
96+
}
97+
98+
internal static void ReadPkcs8<TRet, TState>(
99+
string[] validOids,
100+
ReadOnlySpan<byte> source,
101+
TState state,
102+
KeyReader<TRet, TState> keyReader,
103+
out int bytesRead,
104+
out TRet ret)
105+
#if NET
106+
where TState : allows ref struct
107+
#endif
81108
{
82109
try
83110
{
@@ -91,7 +118,7 @@ internal static void ReadPkcs8<TRet>(
91118
}
92119

93120
// Fails if there are unconsumed bytes.
94-
keyReader(privateKeyInfo.PrivateKey, privateKeyInfo.PrivateKeyAlgorithm, out ret);
121+
keyReader(privateKeyInfo.PrivateKey, state, privateKeyInfo.PrivateKeyAlgorithm, out ret);
95122
bytesRead = read;
96123
}
97124
catch (AsnContentException e)

0 commit comments

Comments
 (0)