Skip to content

Commit e749b39

Browse files
[PQC] Update tests for latest Win11 Insiders (#118612)
1 parent 29bbab4 commit e749b39

File tree

7 files changed

+77
-199
lines changed

7 files changed

+77
-199
lines changed

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

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Diagnostics;
55
using System.Formats.Asn1;
66
using System.Security.Cryptography.Asn1;
7-
using System.Runtime.InteropServices;
87
using System.Runtime.Versioning;
98
using Microsoft.Win32.SafeHandles;
109

@@ -373,16 +372,6 @@ internal static MLDsaCng ImportPkcs8PrivateKey(byte[] source, out int bytesRead)
373372
{
374373
key = CngKey.Import(pkcs8Source, CngKeyBlobFormat.Pkcs8PrivateBlob);
375374
}
376-
catch (CryptographicException)
377-
{
378-
// TODO: Once Windows moves to new PKCS#8 format, we can remove this conversion.
379-
byte[] newPkcs8Source = MLDsaPkcs8.ConvertToOldChoicelessFormat(pkcs8Source);
380-
381-
using (PinAndClear.Track(newPkcs8Source))
382-
{
383-
key = CngKey.Import(newPkcs8Source, CngKeyBlobFormat.Pkcs8PrivateBlob);
384-
}
385-
}
386375
catch (AsnContentException e)
387376
{
388377
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
@@ -491,13 +480,6 @@ private void ExportKeyWithEncryptedOnlyExport(KeySelectorFunc keySelector, MLDsa
491480
{
492481
mldsaPrivateKeyAsn = MLDsaPrivateKeyAsn.Decode(privateKey, AsnEncodingRules.BER);
493482
}
494-
catch (CryptographicException)
495-
{
496-
// TODO: Once Windows moves to new PKCS#8 format, we can remove this conversion.
497-
newPkcs8 = MLDsaPkcs8.ConvertFromOldChoicelessFormat(pkcs8);
498-
ReadOnlyMemory<byte> newPrivateKey = KeyFormatHelper.ReadPkcs8(KnownOids, newPkcs8, out _);
499-
mldsaPrivateKeyAsn = MLDsaPrivateKeyAsn.Decode(newPrivateKey, AsnEncodingRules.BER);
500-
}
501483
catch (AsnContentException e)
502484
{
503485
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Buffers;
5-
using System.Diagnostics;
64
using System.Formats.Asn1;
7-
using System.Runtime.InteropServices;
85
using System.Security.Cryptography.Asn1;
96

107
namespace System.Security.Cryptography
@@ -72,74 +69,5 @@ internal static bool TryExportPkcs8PrivateKey(
7269
}
7370
}
7471
}
75-
76-
// TODO: Remove this once Windows moves to the new format.
77-
internal static unsafe byte[] ConvertToOldChoicelessFormat(ReadOnlySpan<byte> pkcs8WithChoice)
78-
{
79-
fixed (byte* ptr = &MemoryMarshal.GetReference(pkcs8WithChoice))
80-
{
81-
using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, pkcs8WithChoice.Length))
82-
{
83-
PrivateKeyInfoAsn privateKeyInfo = PrivateKeyInfoAsn.Decode(manager.Memory, AsnEncodingRules.BER);
84-
AlgorithmIdentifierAsn privateAlgorithm = privateKeyInfo.PrivateKeyAlgorithm;
85-
86-
if (privateAlgorithm.Algorithm is not (Oids.MLDsa44 or Oids.MLDsa65 or Oids.MLDsa87))
87-
{
88-
Debug.Fail("Unexpected algorithm");
89-
throw new CryptographicException();
90-
}
91-
92-
MLDsaPrivateKeyAsn mldsaPrivateKeyAsn = MLDsaPrivateKeyAsn.Decode(privateKeyInfo.PrivateKey, AsnEncodingRules.BER);
93-
privateKeyInfo.PrivateKey = mldsaPrivateKeyAsn.Seed
94-
?? mldsaPrivateKeyAsn.ExpandedKey.GetValueOrDefault(); // Old format does not support having both
95-
96-
AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
97-
privateKeyInfo.Encode(writer);
98-
return writer.Encode();
99-
}
100-
}
101-
}
102-
103-
// TODO: Remove this once Windows moves to the new format.
104-
internal static unsafe byte[] ConvertFromOldChoicelessFormat(ReadOnlySpan<byte> pkcs8WithoutChoice)
105-
{
106-
fixed (byte* ptr = &MemoryMarshal.GetReference(pkcs8WithoutChoice))
107-
{
108-
using (MemoryManager<byte> manager = new PointerMemoryManager<byte>(ptr, pkcs8WithoutChoice.Length))
109-
{
110-
PrivateKeyInfoAsn privateKeyInfo = PrivateKeyInfoAsn.Decode(manager.Memory, AsnEncodingRules.BER);
111-
AlgorithmIdentifierAsn privateAlgorithm = privateKeyInfo.PrivateKeyAlgorithm;
112-
113-
int seedSize = privateAlgorithm.Algorithm switch
114-
{
115-
Oids.MLDsa44 => MLDsaAlgorithm.MLDsa44.PrivateSeedSizeInBytes,
116-
Oids.MLDsa65 => MLDsaAlgorithm.MLDsa65.PrivateSeedSizeInBytes,
117-
Oids.MLDsa87 => MLDsaAlgorithm.MLDsa87.PrivateSeedSizeInBytes,
118-
_ => throw new CryptographicException(),
119-
};
120-
121-
ReadOnlyMemory<byte> key = privateKeyInfo.PrivateKey;
122-
123-
MLDsaPrivateKeyAsn mldsaPrivateKeyAsn = default;
124-
125-
if (key.Length == seedSize)
126-
{
127-
mldsaPrivateKeyAsn.Seed = key;
128-
}
129-
else
130-
{
131-
mldsaPrivateKeyAsn.ExpandedKey = key;
132-
}
133-
134-
AsnWriter writer = new(AsnEncodingRules.DER);
135-
mldsaPrivateKeyAsn.Encode(writer);
136-
privateKeyInfo.PrivateKey = writer.Encode();
137-
138-
writer = new AsnWriter(AsnEncodingRules.DER);
139-
privateKeyInfo.Encode(writer);
140-
return writer.Encode();
141-
}
142-
}
143-
}
14472
}
14573
}

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/MLDsa/MLDsaCngTests.Windows.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public void ImportPrivateSeed_Persisted()
144144
}
145145
}
146146

147-
[Fact]
147+
[ConditionalFact(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.SupportsExportingPrivateKeyPkcs8))]
148148
public void ImportPrivateKey_Persisted()
149149
{
150150
CngKey key = PqcBlobHelpers.EncodeMLDsaBlob(

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/MLDsa/MLDsaTestHelpers.cs

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,8 @@ internal static partial class MLDsaTestHelpers
1414
{
1515
internal static bool MLDsaIsNotSupported => !MLDsa.IsSupported;
1616

17-
// TODO: Windows does not support draft 10 PKCS#8 format yet. Remove this and use MLDsa.IsSupported (or remove condition) when it does.
18-
internal static bool SupportsDraft10Pkcs8 => MLDsa.IsSupported && !PlatformDetection.IsWindows;
19-
20-
// TODO: Windows does not support signing empty data. Remove this and use MLDsa.IsSupported (or remove condition) when it does.
21-
internal static bool SigningEmptyDataIsSupported => MLDsa.IsSupported && !PlatformDetection.IsWindows;
17+
// TODO (https://github.com/dotnet/runtime/issues/118609): Windows currently does not support PKCS#8 export when imported as private key.
18+
internal static bool SupportsExportingPrivateKeyPkcs8 => MLDsa.IsSupported && !PlatformDetection.IsWindows;
2219

2320
internal static bool ExternalMuIsSupported => MLDsa.IsSupported && !PlatformDetection.IsWindows;
2421

@@ -305,28 +302,11 @@ internal static void AssertExportMLDsaPrivateKey(Action<Func<MLDsa, byte[]>> dir
305302

306303
AssertExportPkcs8PrivateKey(exportPkcs8 =>
307304
indirectCallback(mldsa =>
308-
DecodeExpandedKey(
309-
mldsa,
305+
MLDsaPrivateKeyAsn.Decode(
310306
PrivateKeyInfoAsn.Decode(
311307
exportPkcs8(mldsa), AsnEncodingRules.DER).PrivateKey, AsnEncodingRules.DER).ExpandedKey?.ToArray()));
312308
}
313309

314-
// TODO remove this when windows supports draft 10 PKCS#8 format
315-
internal static MLDsaPrivateKeyAsn DecodeExpandedKey(MLDsa mldsa, ReadOnlyMemory<byte> encoded, AsnEncodingRules ruleSet)
316-
{
317-
try
318-
{
319-
return MLDsaPrivateKeyAsn.Decode(encoded, ruleSet);
320-
}
321-
catch (CryptographicException) when (!SupportsDraft10Pkcs8)
322-
{
323-
return new MLDsaPrivateKeyAsn
324-
{
325-
ExpandedKey = (mldsa.Algorithm.PrivateKeySizeInBytes == encoded.Length) ? encoded : default(ReadOnlyMemory<byte>?),
326-
};
327-
}
328-
}
329-
330310
internal static void AssertExportMLDsaPrivateSeed(Action<Func<MLDsa, byte[]>> callback) =>
331311
AssertExportMLDsaPrivateSeed(callback, callback);
332312

@@ -341,28 +321,11 @@ internal static void AssertExportMLDsaPrivateSeed(Action<Func<MLDsa, byte[]>> di
341321

342322
AssertExportPkcs8PrivateKey(exportPkcs8 =>
343323
indirectCallback(mldsa =>
344-
DecodePrivateSeed(
345-
mldsa,
324+
MLDsaPrivateKeyAsn.Decode(
346325
PrivateKeyInfoAsn.Decode(
347326
exportPkcs8(mldsa), AsnEncodingRules.DER).PrivateKey, AsnEncodingRules.DER).Seed?.ToArray()));
348327
}
349328

350-
// TODO remove this when windows supports draft 10 PKCS#8 format
351-
internal static MLDsaPrivateKeyAsn DecodePrivateSeed(MLDsa mldsa, ReadOnlyMemory<byte> encoded, AsnEncodingRules ruleSet)
352-
{
353-
try
354-
{
355-
return MLDsaPrivateKeyAsn.Decode(encoded, ruleSet);
356-
}
357-
catch (CryptographicException) when (!SupportsDraft10Pkcs8)
358-
{
359-
return new MLDsaPrivateKeyAsn
360-
{
361-
Seed = (mldsa.Algorithm.PrivateSeedSizeInBytes == encoded.Length) ? encoded : default(ReadOnlyMemory<byte>?),
362-
};
363-
}
364-
}
365-
366329
internal static void AssertExportPkcs8PrivateKey(MLDsa mldsa, Action<byte[]> callback) =>
367330
AssertExportPkcs8PrivateKey(export => callback(export(mldsa)));
368331

src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/MLDsa/MLDsaTestsBase.cs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@ public void GenerateSignVerifyExternalMuWithContext(MLDsaAlgorithm algorithm)
8989
SignAndVerifyExternalMu(mldsa, data, context);
9090
}
9191

92-
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.SigningEmptyDataIsSupported))]
93-
[ActiveIssue("https://github.com/dotnet/runtime/issues/116461", TestPlatforms.Windows)]
92+
[Theory]
9493
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
9594
public void GenerateSignVerifyEmptyMessageNoContext(MLDsaAlgorithm algorithm)
9695
{
@@ -99,8 +98,7 @@ public void GenerateSignVerifyEmptyMessageNoContext(MLDsaAlgorithm algorithm)
9998
ExerciseSuccessfulVerify(mldsa, [], signature, []);
10099
}
101100

102-
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.SigningEmptyDataIsSupported))]
103-
[ActiveIssue("https://github.com/dotnet/runtime/issues/116461", TestPlatforms.Windows)]
101+
[Theory]
104102
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
105103
public void GenerateSignVerifyEmptyMessageWithContext(MLDsaAlgorithm algorithm)
106104
{
@@ -110,19 +108,15 @@ public void GenerateSignVerifyEmptyMessageWithContext(MLDsaAlgorithm algorithm)
110108
ExerciseSuccessfulVerify(mldsa, [], signature, context);
111109
}
112110

113-
[ConditionalTheory(
114-
typeof(MLDsaTestHelpers),
115-
[nameof(MLDsaTestHelpers.SigningEmptyDataIsSupported), nameof(MLDsaTestHelpers.ExternalMuIsSupported)])]
111+
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.ExternalMuIsSupported))]
116112
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
117113
public void GenerateSignVerifyEmptyMessageExternalMuNoContext(MLDsaAlgorithm algorithm)
118114
{
119115
using MLDsa mldsa = GenerateKey(algorithm);
120116
SignAndVerifyExternalMu(mldsa, [], []);
121117
}
122118

123-
[ConditionalTheory(
124-
typeof(MLDsaTestHelpers),
125-
[nameof(MLDsaTestHelpers.SigningEmptyDataIsSupported), nameof(MLDsaTestHelpers.ExternalMuIsSupported)])]
119+
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.ExternalMuIsSupported))]
126120
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
127121
public void GenerateSignVerifyEmptyMessageExternalMuWithContext(MLDsaAlgorithm algorithm)
128122
{
@@ -228,7 +222,7 @@ public void GenerateExportPrivateSeedSignAndVerify(MLDsaAlgorithm algorithm)
228222
}
229223
}
230224

231-
[Fact]
225+
[ConditionalFact(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.SupportsExportingPrivateKeyPkcs8))]
232226
public void ImportPrivateKey_CannotReconstructSeed()
233227
{
234228
byte[] privateKey;
@@ -295,7 +289,7 @@ public void NistImportPublicKeyVerifyExternalMu(MLDsaNistTestCase testCase)
295289
Assert.Equal(testCase.ShouldPass, mldsa.VerifyMu(testCase.Mu, testCase.Signature));
296290
}
297291

298-
[Theory]
292+
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.SupportsExportingPrivateKeyPkcs8))]
299293
[MemberData(nameof(MLDsaTestsData.AllPureMLDsaNistTestCases), MemberType = typeof(MLDsaTestsData))]
300294
public void NistImportPrivateKeyVerifyExportsAndSignature(MLDsaNistTestCase testCase)
301295
{
@@ -332,7 +326,7 @@ public void ImportPublicKey_Export(MLDsaKeyInfo info)
332326
export => AssertExportPkcs8FromPublicKey(() => export(mldsa)));
333327
}
334328

335-
[Theory]
329+
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.SupportsExportingPrivateKeyPkcs8))]
336330
[MemberData(nameof(MLDsaTestsData.IetfMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
337331
public void ImportPrivateKey_Export(MLDsaKeyInfo info)
338332
{

src/libraries/System.Security.Cryptography/tests/X509Certificates/ExportTests.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.Collections.Generic;
54
using System.Formats.Asn1;
6-
using System.Linq;
75
using System.Security.Cryptography.Tests;
86
using System.Security.Cryptography.Dsa.Tests;
97
using System.Security.Cryptography.EcDsa.Tests;
@@ -370,7 +368,7 @@ public static void ExportPkcs12_MLKem_Roundtrip(MLKemAlgorithm algorithm)
370368

371369
PbeParameters pbeParameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 32);
372370

373-
using (X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(pfxBytes, pfxPassword))
371+
using (X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(pfxBytes, pfxPassword, X509KeyStorageFlags.Exportable))
374372
{
375373
byte[] pkcs12 = cert.ExportPkcs12(pbeParameters, password);
376374
(int certs, int keys) = VerifyPkcs12(
@@ -382,7 +380,7 @@ public static void ExportPkcs12_MLKem_Roundtrip(MLKemAlgorithm algorithm)
382380
Assert.Equal(1, certs);
383381
Assert.Equal(1, keys);
384382

385-
using (X509Certificate2 reLoaded = X509CertificateLoader.LoadPkcs12(pkcs12, password))
383+
using (X509Certificate2 reLoaded = X509CertificateLoader.LoadPkcs12(pkcs12, password, X509KeyStorageFlags.Exportable))
386384
using (MLKem kem = reLoaded.GetMLKemPrivateKey())
387385
{
388386
Assert.NotNull(kem);
@@ -392,15 +390,14 @@ public static void ExportPkcs12_MLKem_Roundtrip(MLKemAlgorithm algorithm)
392390
}
393391
}
394392

395-
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.SupportsDraft10Pkcs8))]
396-
[ActiveIssue("https://github.com/dotnet/runtime/issues/116463", TestPlatforms.Windows)]
393+
[ConditionalTheory(typeof(MLDsa), nameof(MLDsa.IsSupported))]
397394
[MemberData(nameof(MLDsaTestsData.IetfMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
398395
public static void ExportPkcs12_MLDsa_Generated_Roundtrip(MLDsaKeyInfo info)
399396
{
400397
string password = info.EncryptionPassword;
401398
PbeParameters pbeParameters = info.EncryptionParameters;
402399

403-
using (X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(info.Pfx_Seed, password))
400+
using (X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(info.Pfx_Seed, password, X509KeyStorageFlags.Exportable))
404401
{
405402
byte[] pkcs12 = cert.ExportPkcs12(pbeParameters, password);
406403
(int certs, int keys) = VerifyPkcs12(
@@ -412,7 +409,7 @@ public static void ExportPkcs12_MLDsa_Generated_Roundtrip(MLDsaKeyInfo info)
412409
Assert.Equal(1, certs);
413410
Assert.Equal(1, keys);
414411

415-
using (X509Certificate2 reLoaded = X509CertificateLoader.LoadPkcs12(pkcs12, password))
412+
using (X509Certificate2 reLoaded = X509CertificateLoader.LoadPkcs12(pkcs12, password, X509KeyStorageFlags.Exportable))
416413
using (MLDsa mldsa = reLoaded.GetMLDsaPrivateKey())
417414
{
418415
Assert.NotNull(mldsa);
@@ -433,7 +430,7 @@ public static void ExportPkcs12_SlhDsa_Ietf_Roundtrip()
433430

434431
PbeParameters pbeParameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 32);
435432

436-
using (X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(pfxBytes, password))
433+
using (X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(pfxBytes, password, X509KeyStorageFlags.Exportable))
437434
{
438435
byte[] pkcs12 = cert.ExportPkcs12(pbeParameters, password);
439436
(int certs, int keys) = VerifyPkcs12(
@@ -445,7 +442,7 @@ public static void ExportPkcs12_SlhDsa_Ietf_Roundtrip()
445442
Assert.Equal(1, certs);
446443
Assert.Equal(1, keys);
447444

448-
using (X509Certificate2 reLoaded = X509CertificateLoader.LoadPkcs12(pkcs12, password))
445+
using (X509Certificate2 reLoaded = X509CertificateLoader.LoadPkcs12(pkcs12, password, X509KeyStorageFlags.Exportable))
449446
using (SlhDsa slhDsa = reLoaded.GetSlhDsaPrivateKey())
450447
{
451448
Assert.NotNull(slhDsa);
@@ -462,7 +459,7 @@ public static void ExportPkcs12_SlhDsa_Generated_Roundtrip(SlhDsaTestData.SlhDsa
462459
string password = info.EncryptionPassword;
463460
PbeParameters pbeParameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 32);
464461

465-
using (X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(info.SelfSignedCertificatePfx, password))
462+
using (X509Certificate2 cert = X509CertificateLoader.LoadPkcs12(info.SelfSignedCertificatePfx, password, X509KeyStorageFlags.Exportable))
466463
{
467464
byte[] pkcs12 = cert.ExportPkcs12(pbeParameters, password);
468465
(int certs, int keys) = VerifyPkcs12(
@@ -474,7 +471,7 @@ public static void ExportPkcs12_SlhDsa_Generated_Roundtrip(SlhDsaTestData.SlhDsa
474471
Assert.Equal(1, certs);
475472
Assert.Equal(1, keys);
476473

477-
using (X509Certificate2 reLoaded = X509CertificateLoader.LoadPkcs12(pkcs12, password))
474+
using (X509Certificate2 reLoaded = X509CertificateLoader.LoadPkcs12(pkcs12, password, X509KeyStorageFlags.Exportable))
478475
using (SlhDsa slhDsa = reLoaded.GetSlhDsaPrivateKey())
479476
{
480477
Assert.NotNull(slhDsa);

0 commit comments

Comments
 (0)