Skip to content

Commit b2a7d31

Browse files
PreHash SLH-DSA (#115509)
1 parent b581381 commit b2a7d31

File tree

21 files changed

+1549
-20
lines changed

21 files changed

+1549
-20
lines changed

src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.SlhDsa.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,58 @@ internal static bool SlhDsaVerifyPure(
131131
}
132132
}
133133

134+
[LibraryImport(Libraries.CryptoNative)]
135+
private static partial int CryptoNative_SlhDsaSignPreEncoded(
136+
SafeEvpPKeyHandle pkey, IntPtr extraHandle,
137+
ReadOnlySpan<byte> msg, int msgLength,
138+
Span<byte> destination, int destinationLength);
139+
140+
internal static void SlhDsaSignPreEncoded(
141+
SafeEvpPKeyHandle pkey,
142+
ReadOnlySpan<byte> msg,
143+
Span<byte> destination)
144+
{
145+
int ret = CryptoNative_SlhDsaSignPreEncoded(
146+
pkey, GetExtraHandle(pkey),
147+
msg, msg.Length,
148+
destination, destination.Length);
149+
150+
if (ret != 1)
151+
{
152+
throw Interop.Crypto.CreateOpenSslCryptographicException();
153+
}
154+
}
155+
156+
[LibraryImport(Libraries.CryptoNative)]
157+
private static partial int CryptoNative_SlhDsaVerifyPreEncoded(
158+
SafeEvpPKeyHandle pkey, IntPtr extraHandle,
159+
ReadOnlySpan<byte> msg, int msgLength,
160+
ReadOnlySpan<byte> signature, int signatureLength);
161+
162+
internal static bool SlhDsaVerifyPreEncoded(
163+
SafeEvpPKeyHandle pkey,
164+
ReadOnlySpan<byte> msg,
165+
ReadOnlySpan<byte> signature)
166+
{
167+
int ret = CryptoNative_SlhDsaVerifyPreEncoded(
168+
pkey, GetExtraHandle(pkey),
169+
msg, msg.Length,
170+
signature, signature.Length);
171+
172+
if (ret == 1)
173+
{
174+
return true;
175+
}
176+
else if (ret == 0)
177+
{
178+
return false;
179+
}
180+
else
181+
{
182+
throw Interop.Crypto.CreateOpenSslCryptographicException();
183+
}
184+
}
185+
134186
[LibraryImport(Libraries.CryptoNative)]
135187
private static partial int CryptoNative_SlhDsaExportSecretKey(SafeEvpPKeyHandle pkey, Span<byte> destination, int destinationLength);
136188

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

Lines changed: 307 additions & 7 deletions
Large diffs are not rendered by default.

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ protected override void SignDataCore(ReadOnlySpan<byte> data, ReadOnlySpan<byte>
2323
protected override bool VerifyDataCore(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context, ReadOnlySpan<byte> signature) =>
2424
throw new PlatformNotSupportedException();
2525

26+
protected override void SignPreHashCore(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination) =>
27+
throw new PlatformNotSupportedException();
28+
29+
protected override bool VerifyPreHashCore(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature) =>
30+
throw new PlatformNotSupportedException();
31+
2632
protected override void ExportSlhDsaPublicKeyCore(Span<byte> destination) =>
2733
throw new PlatformNotSupportedException();
2834

src/libraries/Common/src/System/Security/Cryptography/SlhDsaImplementation.Windows.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ protected override void SignDataCore(ReadOnlySpan<byte> data, ReadOnlySpan<byte>
2323
protected override bool VerifyDataCore(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context, ReadOnlySpan<byte> signature) =>
2424
throw new PlatformNotSupportedException();
2525

26+
protected override void SignPreHashCore(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination) =>
27+
throw new PlatformNotSupportedException();
28+
29+
protected override bool VerifyPreHashCore(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature) =>
30+
throw new PlatformNotSupportedException();
31+
2632
protected override void ExportSlhDsaPublicKeyCore(Span<byte> destination) =>
2733
throw new PlatformNotSupportedException();
2834

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/SlhDsa/SlhDsaContractTests.cs

Lines changed: 275 additions & 1 deletion
Large diffs are not rendered by default.

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/SlhDsa/SlhDsaMockImplementation.cs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ public SlhDsaMockImplementation(SlhDsaAlgorithm algorithm)
2929
public delegate bool TryExportPkcs8PrivateKeyCoreFunc(Span<byte> destination, out int bytesWritten);
3030
public delegate void SignDataCoreAction(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context, Span<byte> s);
3131
public delegate bool VerifyDataCoreFunc(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context, ReadOnlySpan<byte> signature);
32+
public delegate void SignPreHashCoreAction(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination);
33+
public delegate bool VerifyPreHashCoreFunc(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature);
3234
public delegate void DisposeAction(bool disposing);
3335

3436
public TryExportPkcs8PrivateKeyCoreFunc BaseTryExportPkcs8PrivateKeyCore =>
3537
base.TryExportPkcs8PrivateKeyCore;
3638

3739
public int VerifyDataCoreCallCount = 0;
3840
public int SignDataCoreCallCount = 0;
41+
public int VerifyPreHashCoreCallCount = 0;
42+
public int SignPreHashCoreCallCount = 0;
3943
public int ExportSlhDsaPublicKeyCoreCallCount = 0;
4044
public int ExportSlhDsaSecretKeyCoreCallCount = 0;
4145
public int TryExportPkcs8PrivateKeyCoreCallCount = 0;
@@ -47,6 +51,8 @@ public SlhDsaMockImplementation(SlhDsaAlgorithm algorithm)
4751
(_, out bytesWritten) => { Assert.Fail(); bytesWritten = 0; return false; };
4852
public SignDataCoreAction SignDataCoreHook { get; set; } = (_, _, _) => Assert.Fail();
4953
public VerifyDataCoreFunc VerifyDataCoreHook { get; set; } = (_, _, _) => { Assert.Fail(); return false; };
54+
public SignPreHashCoreAction SignPreHashCoreHook { get; set; } = (_, _, _, _) => Assert.Fail();
55+
public VerifyPreHashCoreFunc VerifyPreHashCoreHook { get; set; } = (_, _, _, _) => { Assert.Fail(); return false; };
5056
public DisposeAction DisposeHook { get; set; } = _ => { };
5157

5258
protected override void ExportSlhDsaPublicKeyCore(Span<byte> destination)
@@ -85,6 +91,18 @@ protected override bool VerifyDataCore(ReadOnlySpan<byte> data, ReadOnlySpan<byt
8591
return VerifyDataCoreHook(data, context, signature);
8692
}
8793

94+
protected override void SignPreHashCore(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination)
95+
{
96+
SignPreHashCoreCallCount++;
97+
SignPreHashCoreHook(hash, context, hashAlgorithmOid, destination);
98+
}
99+
100+
protected override bool VerifyPreHashCore(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature)
101+
{
102+
VerifyPreHashCoreCallCount++;
103+
return VerifyPreHashCoreHook(hash, context, hashAlgorithmOid, signature);
104+
}
105+
88106
public void AddLengthAssertion()
89107
{
90108
ExportSlhDsaPublicKeyCoreAction oldExportSlhDsaPublicKeyCoreHook = ExportSlhDsaPublicKeyCoreHook;
@@ -115,6 +133,21 @@ public void AddLengthAssertion()
115133
Assert.Equal(Algorithm.SignatureSizeInBytes, signature.Length);
116134
return ret;
117135
};
136+
137+
SignPreHashCoreAction oldSignPreHashCoreHook = SignPreHashCoreHook;
138+
SignPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination) =>
139+
{
140+
oldSignDataCoreHook(hash, context, destination);
141+
Assert.Equal(Algorithm.SignatureSizeInBytes, destination.Length);
142+
};
143+
144+
VerifyPreHashCoreFunc oldVerifyPreHashCoreHook = VerifyPreHashCoreHook;
145+
VerifyPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature) =>
146+
{
147+
bool ret = oldVerifyPreHashCoreHook(hash, context, hashAlgorithmOid, signature);
148+
Assert.Equal(Algorithm.SignatureSizeInBytes, signature.Length);
149+
return ret;
150+
};
118151
}
119152

120153
public void AddDestinationBufferIsSameAssertion(ReadOnlyMemory<byte> buffer)
@@ -140,6 +173,13 @@ public void AddDestinationBufferIsSameAssertion(ReadOnlyMemory<byte> buffer)
140173
AssertExtensions.Same(buffer.Span, destination);
141174
};
142175

176+
SignPreHashCoreAction oldSignPreHashCoreHook = SignPreHashCoreHook;
177+
SignPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination) =>
178+
{
179+
oldSignPreHashCoreHook(hash, context, hashAlgorithmOid, destination);
180+
AssertExtensions.Same(buffer.Span, destination);
181+
};
182+
143183
TryExportPkcs8PrivateKeyCoreFunc oldTryExportPkcs8PrivateKeyCoreHook = TryExportPkcs8PrivateKeyCoreHook;
144184
TryExportPkcs8PrivateKeyCoreHook = (Span<byte> destination, out int bytesWritten) =>
145185
{
@@ -165,6 +205,21 @@ public void AddContextBufferIsSameAssertion(ReadOnlyMemory<byte> buffer)
165205
AssertExtensions.Same(buffer.Span, context);
166206
return ret;
167207
};
208+
209+
SignPreHashCoreAction oldSignPreHashCoreHook = SignPreHashCoreHook;
210+
SignPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination) =>
211+
{
212+
oldSignPreHashCoreHook(hash, context, hashAlgorithmOid, destination);
213+
AssertExtensions.Same(buffer.Span, context);
214+
};
215+
216+
VerifyPreHashCoreFunc oldVerifyPreHashCoreHook = VerifyPreHashCoreHook;
217+
VerifyPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature) =>
218+
{
219+
bool ret = oldVerifyPreHashCoreHook(hash, context, hashAlgorithmOid, signature);
220+
AssertExtensions.Same(buffer.Span, context);
221+
return ret;
222+
};
168223
}
169224

170225
public void AddSignatureBufferIsSameAssertion(ReadOnlyMemory<byte> buffer)
@@ -176,6 +231,14 @@ public void AddSignatureBufferIsSameAssertion(ReadOnlyMemory<byte> buffer)
176231
AssertExtensions.Same(buffer.Span, signature);
177232
return ret;
178233
};
234+
235+
VerifyPreHashCoreFunc oldVerifyPreHashCoreHook = VerifyPreHashCoreHook;
236+
VerifyPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature) =>
237+
{
238+
bool ret = oldVerifyPreHashCoreHook(hash, context, hashAlgorithmOid, signature);
239+
AssertExtensions.Same(buffer.Span, signature);
240+
return ret;
241+
};
179242
}
180243

181244
public void AddDataBufferIsSameAssertion(ReadOnlyMemory<byte> buffer)
@@ -194,6 +257,39 @@ public void AddDataBufferIsSameAssertion(ReadOnlyMemory<byte> buffer)
194257
AssertExtensions.Same(buffer.Span, data);
195258
return ret;
196259
};
260+
261+
SignPreHashCoreAction oldSignPreHashCoreHook = SignPreHashCoreHook;
262+
SignPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination) =>
263+
{
264+
oldSignPreHashCoreHook(hash, context, hashAlgorithmOid, destination);
265+
AssertExtensions.Same(buffer.Span, hash);
266+
};
267+
268+
VerifyPreHashCoreFunc oldVerifyPreHashCoreHook = VerifyPreHashCoreHook;
269+
VerifyPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature) =>
270+
{
271+
bool ret = oldVerifyPreHashCoreHook(hash, context, hashAlgorithmOid, signature);
272+
AssertExtensions.Same(buffer.Span, hash);
273+
return ret;
274+
};
275+
}
276+
277+
public void AddHashAlgorithmIsSameAssertion(ReadOnlyMemory<char> buffer)
278+
{
279+
SignPreHashCoreAction oldSignPreHashCoreHook = SignPreHashCoreHook;
280+
SignPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination) =>
281+
{
282+
oldSignPreHashCoreHook(hash, context, hashAlgorithmOid, destination);
283+
AssertExtensions.Same(buffer.Span, hashAlgorithmOid);
284+
};
285+
286+
VerifyPreHashCoreFunc oldVerifyPreHashCoreHook = VerifyPreHashCoreHook;
287+
VerifyPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature) =>
288+
{
289+
bool ret = oldVerifyPreHashCoreHook(hash, context, hashAlgorithmOid, signature);
290+
AssertExtensions.Same(buffer.Span, hashAlgorithmOid);
291+
return ret;
292+
};
197293
}
198294

199295
public void AddFillDestination(byte b)
@@ -219,6 +315,13 @@ public void AddFillDestination(byte b)
219315
destination.Fill(b);
220316
};
221317

318+
SignPreHashCoreAction oldSignPreHashCoreHook = SignPreHashCoreHook;
319+
SignPreHashCoreHook = (ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination) =>
320+
{
321+
oldSignPreHashCoreHook(hash, context, hashAlgorithmOid, destination);
322+
destination.Fill(b);
323+
};
324+
222325
TryExportPkcs8PrivateKeyCoreFunc oldTryExportPkcs8PrivateKeyCoreHook = TryExportPkcs8PrivateKeyCoreHook;
223326
TryExportPkcs8PrivateKeyCoreHook = (Span<byte> destination, out int bytesWritten) =>
224327
{

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/SlhDsa/SlhDsaTestData.cs

Lines changed: 300 additions & 3 deletions
Large diffs are not rendered by default.

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/SlhDsa/SlhDsaTestHelpers.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ internal static void VerifyDisposed(SlhDsa slhDsa)
2828
Assert.Throws<ObjectDisposedException>(() => slhDsa.VerifyData(ReadOnlySpan<byte>.Empty, tempBuffer.AsSpan(), ReadOnlySpan<byte>.Empty));
2929
Assert.Throws<ObjectDisposedException>(() => slhDsa.VerifyData(Array.Empty<byte>(), tempBuffer, Array.Empty<byte>()));
3030

31+
Assert.Throws<ObjectDisposedException>(() => slhDsa.SignPreHash(ReadOnlySpan<byte>.Empty, tempBuffer.AsSpan(), "1.0", ReadOnlySpan<byte>.Empty));
32+
Assert.Throws<ObjectDisposedException>(() => slhDsa.SignPreHash(Array.Empty<byte>(), "1.0"));
33+
Assert.Throws<ObjectDisposedException>(() => slhDsa.VerifyPreHash(ReadOnlySpan<byte>.Empty, tempBuffer.AsSpan(), "1.0", ReadOnlySpan<byte>.Empty));
34+
Assert.Throws<ObjectDisposedException>(() => slhDsa.VerifyPreHash(Array.Empty<byte>(), tempBuffer.AsSpan(), "1.0", Array.Empty<byte>()));
35+
3136
Assert.Throws<ObjectDisposedException>(() => slhDsa.ExportEncryptedPkcs8PrivateKey(ReadOnlySpan<byte>.Empty, pbeParameters));
3237
Assert.Throws<ObjectDisposedException>(() => slhDsa.ExportEncryptedPkcs8PrivateKey(ReadOnlySpan<char>.Empty, pbeParameters));
3338
Assert.Throws<ObjectDisposedException>(() => slhDsa.ExportEncryptedPkcs8PrivateKeyPem(ReadOnlySpan<byte>.Empty, pbeParameters));
@@ -386,5 +391,16 @@ internal static byte[] DoTryUntilDone(TryExportFunc func)
386391
_ => null,
387392
};
388393
}
394+
395+
internal const string Md5Oid = "1.2.840.113549.2.5";
396+
internal const string Sha1Oid = "1.3.14.3.2.26";
397+
internal const string Sha256Oid = "2.16.840.1.101.3.4.2.1";
398+
internal const string Sha384Oid = "2.16.840.1.101.3.4.2.2";
399+
internal const string Sha512Oid = "2.16.840.1.101.3.4.2.3";
400+
internal const string Sha3_256Oid = "2.16.840.1.101.3.4.2.8";
401+
internal const string Sha3_384Oid = "2.16.840.1.101.3.4.2.9";
402+
internal const string Sha3_512Oid = "2.16.840.1.101.3.4.2.10";
403+
internal const string Shake128Oid = "2.16.840.1.101.3.4.2.11";
404+
internal const string Shake256Oid = "2.16.840.1.101.3.4.2.12";
389405
}
390406
}

0 commit comments

Comments
 (0)