Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ namespace System.Security.Cryptography.Pkcs.Tests
[ActiveIssue("https://github.com/dotnet/runtime/issues/126697", typeof(PlatformDetection), nameof(PlatformDetection.IsAppleMobile), nameof(PlatformDetection.IsNativeAot))]
public static partial class SignedCmsTests
{
// TODO: Windows does not support draft 10 PKCS#8 format yet. Remove this and use MLDsa.IsSupported when it does.
public static bool SupportsDraft10Pkcs8 => MLDsa.IsSupported && !PlatformDetection.IsWindows;

[Fact]
public static void DefaultStateBehavior()
{
Expand Down Expand Up @@ -668,25 +665,41 @@ public static void AddFirstSigner_SlhDsa(SubjectIdentifierType identifierType, b
}
select new object[] { sit, detached, data.hashAlgorithm, data.algorithm };

[ConditionalTheory(typeof(SignedCmsTests), nameof(SupportsDraft10Pkcs8))]
[ConditionalTheory(typeof(MLDsa), nameof(MLDsa.IsSupported))]
[MemberData(nameof(AddFirstSignerMLDsaTestData))]
public static void AddFirstSigner_MLDsa(SubjectIdentifierType identifierType, bool detached, string digestOid, MLDsaAlgorithm algorithm)
{
void SignWithMLDsa(SignedCms cms)
{
using (X509Certificate2 signerCert = Certificates.MLDsaIetf[algorithm].TryGetCertificateWithPrivateKey())
{
CmsSigner signer = new CmsSigner(identifierType, signerCert);
signer.IncludeOption = X509IncludeOption.EndCertOnly;
signer.DigestAlgorithm = new Oid(digestOid, digestOid);
cms.ComputeSignature(signer);
}
}

if (PlatformDetection.IsNetFramework && (digestOid == Oids.Shake128 || digestOid == Oids.Shake256))
{
const int CryptEUnknownAlgorithm = unchecked((int)0x80091002);

// .NET Framework's CMS is backed by Windows CAPI, which does not recognize SHAKE
// digest algorithms and fails signing with CRYPT_E_UNKNOWN_ALGO. .NET builds the
// CMS in managed code and succeeds.
ContentInfo contentInfo = new ContentInfo(new byte[] { 9, 8, 7, 6, 5 });
SignedCms cms = new SignedCms(contentInfo, detached);
CryptographicException exception = Assert.Throws<CryptographicException>(() => SignWithMLDsa(cms));
Assert.Equal(CryptEUnknownAlgorithm, exception.HResult);
return;
}

byte[]? signature = null;

AssertAddFirstSigner(
identifierType,
detached,
cms =>
{
using (X509Certificate2 signerCert = Certificates.MLDsaIetf[algorithm].TryGetCertificateWithPrivateKey())
{
CmsSigner signer = new CmsSigner(identifierType, signerCert);
signer.IncludeOption = X509IncludeOption.EndCertOnly;
signer.DigestAlgorithm = new Oid(digestOid, digestOid);
cms.ComputeSignature(signer);
}
},
SignWithMLDsa,
firstSigner =>
{
// Store signature for comparison after roundtrip.
Expand Down Expand Up @@ -1802,7 +1815,7 @@ private static void CheckNoSignature(byte[] encoded, bool badOid=false)
}
}

[ConditionalFact(typeof(SignedCmsTests), nameof(SupportsDraft10Pkcs8))]
[ConditionalFact(typeof(MLDsa), nameof(MLDsa.IsSupported))]
public static void ComputeSignature_MLDsa_DefaultDigest()
{
#if !NETFRAMEWORK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public static void SignCmsUsingExplicitECDsaP521Key()
}
}

[ConditionalFact(typeof(SignedCmsTests), nameof(SupportsDraft10Pkcs8))]
[ConditionalFact(typeof(MLDsa), nameof(MLDsa.IsSupported))]
public static void SignCmsUsingExplicitMLDsaKey()
{
using (X509Certificate2 cert = Certificates.MLDsaIetf[MLDsaAlgorithm.MLDsa65].TryGetCertificateWithPrivateKey())
Expand Down Expand Up @@ -158,7 +158,7 @@ public static void CounterSignCmsUsingExplicitECDsaKeyForFirstSignerAndRSAForCou
}
}

[ConditionalFact(typeof(SignedCmsTests), nameof(SupportsDraft10Pkcs8))]
[ConditionalFact(typeof(MLDsa), nameof(MLDsa.IsSupported))]
public static void CounterSignCmsUsingExplicitECDsaKeyForFirstSignerAndMLDsaForCounterSignature()
{
using (X509Certificate2 cert = Certificates.ECDsaP256Win.TryGetCertificateWithPrivateKey())
Expand All @@ -170,7 +170,7 @@ public static void CounterSignCmsUsingExplicitECDsaKeyForFirstSignerAndMLDsaForC
}
}

[ConditionalFact(typeof(SignedCmsTests), nameof(SupportsDraft10Pkcs8))]
[ConditionalFact(typeof(MLDsa), nameof(MLDsa.IsSupported))]
public static void CounterSignCmsUsingExplicitMLDsaKeyForFirstSignerAndRSAForCounterSignature()
{
using (X509Certificate2 cert = Certificates.MLDsaIetf[MLDsaAlgorithm.MLDsa65].TryGetCertificateWithPrivateKey())
Expand Down Expand Up @@ -808,7 +808,7 @@ public static void CreateSignature_Ecdsa_ThrowsWithRsaSignaturePadding()
}
}

[ConditionalFact(typeof(SignedCmsTests), nameof(SupportsDraft10Pkcs8))]
[ConditionalFact(typeof(MLDsa), nameof(MLDsa.IsSupported))]
public static void CreateSignature_MLDsa_ThrowsWithRsaSignaturePadding()
{
ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 });
Expand Down Expand Up @@ -1016,7 +1016,7 @@ public static void ComputeSignature_Ecdsa_Sha3_Roundtrip(string hashAlgorithm)
}
}

[ConditionalTheory(typeof(SignedCmsTests), nameof(SupportsDraft10Pkcs8))]
[ConditionalTheory(typeof(MLDsa), nameof(MLDsa.IsSupported))]
[InlineData(Oids.Sha3_256)]
[InlineData(Oids.Sha3_384)]
[InlineData(Oids.Sha3_512)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,27 +814,40 @@ public static void AddCounterSigner_SlhDsa(SubjectIdentifierType identifierType,
}
select new object[] { sit, data.hashAlgorithm, data.algorithm };

// TODO: Windows does not support draft 10 PKCS#8 format yet. Remove this and use MLDsa.IsSupported when it does.
private static bool SupportsDraft10Pkcs8 => MLDsa.IsSupported && !PlatformDetection.IsWindows;

public static bool MLDsaAndRsaSha1SignaturesSupported => SignatureSupport.SupportsRsaSha1Signatures && SupportsDraft10Pkcs8;
public static bool MLDsaAndRsaSha1SignaturesSupported => SignatureSupport.SupportsRsaSha1Signatures && MLDsa.IsSupported;

[ConditionalTheory(typeof(SignerInfoTests), nameof(MLDsaAndRsaSha1SignaturesSupported))]
[MemberData(nameof(AddCounterSignerMLDsaTestData))]
public static void AddCounterSigner_MLDsa(SubjectIdentifierType identifierType, string digestOid, MLDsaAlgorithm algorithm)
{
void CounterSignWithMLDsa(SignerInfo signer)
{
using (X509Certificate2 signerCert = Certificates.MLDsaIetf[algorithm].TryGetCertificateWithPrivateKey())
{
CmsSigner counterSigner = new CmsSigner(identifierType, signerCert);
counterSigner.IncludeOption = X509IncludeOption.EndCertOnly;
counterSigner.DigestAlgorithm = new Oid(digestOid, digestOid);
signer.ComputeCounterSignature(counterSigner);
}
}

if (PlatformDetection.IsNetFramework && (digestOid == Oids.Shake128 || digestOid == Oids.Shake256))
{
const int CryptEUnknownAlgorithm = unchecked((int)0x80091002);

// .NET Framework's CMS is backed by Windows CAPI, which does not recognize SHAKE
// digest algorithms and fails signing with CRYPT_E_UNKNOWN_ALGO. .NET builds the
// CMS in managed code and succeeds.
SignedCms cms = new SignedCms();
cms.Decode(SignedDocuments.RsaPkcs1OneSignerIssuerAndSerialNumber);
CryptographicException exception = Assert.Throws<CryptographicException>(() => CounterSignWithMLDsa(cms.SignerInfos[0]));
Assert.Equal(CryptEUnknownAlgorithm, exception.HResult);
return;
}

AssertAddCounterSigner(
identifierType,
signer =>
{
using (X509Certificate2 signerCert = Certificates.MLDsaIetf[algorithm].TryGetCertificateWithPrivateKey())
{
CmsSigner counterSigner = new CmsSigner(identifierType, signerCert);
counterSigner.IncludeOption = X509IncludeOption.EndCertOnly;
counterSigner.DigestAlgorithm = new Oid(digestOid, digestOid);
signer.ComputeCounterSignature(counterSigner);
}
},
CounterSignWithMLDsa,
(cms, counterSigner) =>
{
byte[] signature = counterSigner.GetSignature();
Expand Down