diff --git a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs index 7dae6711cf995d..81eaadf28afe2c 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs @@ -29,6 +29,8 @@ private readonly Dictionary _crlPaths public string UriPrefix { get; } + public bool RespondEmpty { get; set; } + private RevocationResponder(HttpListener listener, string uriPrefix) { _listener = listener; @@ -133,7 +135,7 @@ internal void HandleRequest(HttpListenerContext context) catch (Exception) { } - + return; } @@ -159,7 +161,7 @@ private void HandleRequest(HttpListenerContext context, ref bool responded) if (_aiaPaths.TryGetValue(url, out authority)) { - byte[] certData = authority.GetCertData(); + byte[] certData = RespondEmpty ? Array.Empty() : authority.GetCertData(); responded = true; context.Response.StatusCode = 200; @@ -171,7 +173,7 @@ private void HandleRequest(HttpListenerContext context, ref bool responded) if (_crlPaths.TryGetValue(url, out authority)) { - byte[] crl = authority.GetCrl(); + byte[] crl = RespondEmpty ? Array.Empty() : authority.GetCrl(); responded = true; context.Response.StatusCode = 200; @@ -208,7 +210,7 @@ private void HandleRequest(HttpListenerContext context, ref bool responded) return; } - byte[] ocspResponse = authority.BuildOcspResponse(certId, nonce); + byte[] ocspResponse = RespondEmpty ? Array.Empty() : authority.BuildOcspResponse(certId, nonce); responded = true; context.Response.StatusCode = 200; @@ -234,7 +236,7 @@ private void HandleRequest(HttpListenerContext context, ref bool responded) internal static RevocationResponder CreateAndListen() { HttpListener listener = OpenListener(out string uriPrefix); - + RevocationResponder responder = new RevocationResponder(listener, uriPrefix); responder.HandleRequests(); return responder; diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateAssetDownloader.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateAssetDownloader.cs index a273893cd0d413..d826a2842d1fe9 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateAssetDownloader.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/CertificateAssetDownloader.cs @@ -23,14 +23,16 @@ internal static class CertificateAssetDownloader { byte[]? data = DownloadAsset(uri, ref remainingDownloadTime); - if (data == null) + if (data == null || data.Length == 0) { return null; } try { - return new X509Certificate2(data); + X509Certificate2 certificate = new X509Certificate2(data); + certificate.ThrowIfInvalid(); + return certificate; } catch (CryptographicException) { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs index dff33f3b002492..ec1445c8944b30 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs @@ -10,6 +10,38 @@ namespace System.Security.Cryptography.X509Certificates.Tests.RevocationTests { public static class AiaTests { + [Fact] + public static void EmptyAiaResponseIsIgnored() + { + CertificateAuthority.BuildPrivatePki( + PkiOptions.AllRevocation, + out RevocationResponder responder, + out CertificateAuthority root, + out CertificateAuthority intermediate, + out X509Certificate2 endEntity, + pkiOptionsInSubject: false); + + using (responder) + using (root) + using (intermediate) + using (endEntity) + using (ChainHolder holder = new ChainHolder()) + using (X509Certificate2 rootCert = root.CloneIssuerCert()) + using (X509Certificate2 intermediateCert = intermediate.CloneIssuerCert()) + { + responder.RespondEmpty = true; + + X509Chain chain = holder.Chain; + chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; + chain.ChainPolicy.VerificationTime = endEntity.NotBefore.AddMinutes(1); + chain.ChainPolicy.UrlRetrievalTimeout = DynamicRevocationTests.s_urlRetrievalLimit; + chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; + + Assert.False(chain.Build(endEntity)); + Assert.True(chain.AllStatusFlags().HasFlag(X509ChainStatusFlags.PartialChain), "expected partial chain"); + } + } + [Fact] public static void DisableAiaOptionWorks() {