try
{
#endif
- RawData = rawData;
- certificate = CertificateAsn.Decode(rawData, AsnEncodingRules.DER);
+ // Windows and Unix permit trailing data after the DER contents of the certificate, so we will allow
+ // it here, too.
+ AsnValueReader reader = new AsnValueReader(rawData, AsnEncodingRules.DER);
+ ReadOnlySpan<byte> encodedValue = reader.PeekEncodedValue();
+
+ CertificateAsn.Decode(ref reader, rawData, out certificate);
certificate.TbsCertificate.ValidateVersion();
+
+ // Use of == on Span is intentional. If the encodedValue is identical to the rawData, then we can use
+ // raw data as-is, meaning it had no trailing data. Otherwise, use the encodedValue.
+ RawData = encodedValue == rawData ? rawData : encodedValue.ToArray();
+
Issuer = new X500DistinguishedName(certificate.TbsCertificate.Issuer.Span);
Subject = new X500DistinguishedName(certificate.TbsCertificate.Subject.Span);
IssuerName = Issuer.Name;
}
}
+ [Fact]
+ public static void CertificateWithTrailingDataCanBeRead()
+ {
+ byte[] certData = new byte[TestData.MsCertificate.Length + 100];
+ TestData.MsCertificate.AsSpan().CopyTo(certData);
+ certData.AsSpan(TestData.MsCertificate.Length).Fill(0xFF);
+
+ using (X509Certificate2 cert = new X509Certificate2(certData))
+ {
+ Assert.Equal("CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", cert.Subject);
+ Assert.Equal("CN=Microsoft Code Signing PCA, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", cert.Issuer);
+
+ Assert.Equal(TestData.MsCertificate, cert.RawData);
+ }
+ }
+
[ConditionalFact(typeof(PlatformSupport), nameof(PlatformSupport.PlatformCryptoProviderFunctional))]
[OuterLoop("Hardware backed key generation takes several seconds.")]
public static void CreateCertificate_MicrosoftPlatformCryptoProvider_EcdsaKey()