internal static (X509Certificate2 certificate, X509Certificate2Collection) GenerateCertificates(string targetName, [CallerMemberName] string?testName = null) { if (PlatformDetection.IsWindows && testName != null) { CleanupCertificates(testName); } X509Certificate2Collection chain = new X509Certificate2Collection(); X509ExtensionCollection extensions = new X509ExtensionCollection(); SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder(); builder.AddDnsName(targetName); extensions.Add(builder.Build()); extensions.Add(s_eeConstraints); extensions.Add(s_eeKeyUsage); extensions.Add(s_tlsServerEku); CertificateAuthority.BuildPrivatePki( PkiOptions.IssuerRevocationViaCrl, out RevocationResponder responder, out CertificateAuthority root, out CertificateAuthority intermediate, out X509Certificate2 endEntity, subjectName: targetName, testName: testName, keySize: 2048, extensions: extensions); chain.Add(intermediate.CloneIssuerCert()); chain.Add(root.CloneIssuerCert()); responder.Dispose(); root.Dispose(); intermediate.Dispose(); if (PlatformDetection.IsWindows) { endEntity = new X509Certificate2(endEntity.Export(X509ContentType.Pfx)); } return(endEntity, chain); }
internal static (X509Certificate2 certificate, X509Certificate2Collection) GenerateCertificates(string name, string?testName = null) { X509Certificate2Collection chain = new X509Certificate2Collection(); CertificateAuthority.BuildPrivatePki( PkiOptions.IssuerRevocationViaCrl, out RevocationResponder responder, out CertificateAuthority root, out CertificateAuthority intermediate, out X509Certificate2 endEntity, subjectName: name, testName: testName); chain.Add(intermediate.CloneIssuerCert()); chain.Add(root.CloneIssuerCert()); responder.Dispose(); root.Dispose(); intermediate.Dispose(); return(endEntity, chain); }
internal static (X509Certificate2 certificate, X509Certificate2Collection) GenerateCertificates(string targetName, [CallerMemberName] string?testName = null, bool longChain = false, bool serverCertificate = true) { const int keySize = 2048; if (PlatformDetection.IsWindows && testName != null) { CleanupCertificates(testName); } X509Certificate2Collection chain = new X509Certificate2Collection(); X509ExtensionCollection extensions = new X509ExtensionCollection(); SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder(); builder.AddDnsName(targetName); extensions.Add(builder.Build()); extensions.Add(s_eeConstraints); extensions.Add(s_eeKeyUsage); extensions.Add(serverCertificate ? s_tlsServerEku : s_tlsClientEku); CertificateAuthority.BuildPrivatePki( PkiOptions.IssuerRevocationViaCrl, out RevocationResponder responder, out CertificateAuthority root, out CertificateAuthority intermediate, out X509Certificate2 endEntity, subjectName: targetName, testName: testName, keySize: keySize, extensions: extensions); if (longChain) { using (RSA intermedKey2 = RSA.Create(keySize)) using (RSA intermedKey3 = RSA.Create(keySize)) { X509Certificate2 intermedPub2 = intermediate.CreateSubordinateCA( $"CN=\"A SSL Test CA 2\", O=\"testName\"", intermedKey2); X509Certificate2 intermedCert2 = intermedPub2.CopyWithPrivateKey(intermedKey2); intermedPub2.Dispose(); CertificateAuthority intermediateAuthority2 = new CertificateAuthority(intermedCert2, null, null, null); X509Certificate2 intermedPub3 = intermediateAuthority2.CreateSubordinateCA( $"CN=\"A SSL Test CA 3\", O=\"testName\"", intermedKey3); X509Certificate2 intermedCert3 = intermedPub3.CopyWithPrivateKey(intermedKey3); intermedPub3.Dispose(); CertificateAuthority intermediateAuthority3 = new CertificateAuthority(intermedCert3, null, null, null); RSA eeKey = (RSA)endEntity.PrivateKey; endEntity = intermediateAuthority3.CreateEndEntity( $"CN=\"A SSL Test\", O=\"testName\"", eeKey, extensions); endEntity = endEntity.CopyWithPrivateKey(eeKey); chain.Add(intermedCert3); chain.Add(intermedCert2); } } chain.Add(intermediate.CloneIssuerCert()); chain.Add(root.CloneIssuerCert()); responder.Dispose(); root.Dispose(); intermediate.Dispose(); if (PlatformDetection.IsWindows) { endEntity = new X509Certificate2(endEntity.Export(X509ContentType.Pfx)); } return(endEntity, chain); }
private async Task ConnectWithRevocation_WithCallback_Core( X509RevocationMode revocationMode, bool?offlineContext = false) { string offlinePart = offlineContext.HasValue ? offlineContext.GetValueOrDefault().ToString().ToLower() : "null"; string serverName = $"{revocationMode.ToString().ToLower()}.{offlinePart}.server.example"; (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); CertificateAuthority.BuildPrivatePki( PkiOptions.EndEntityRevocationViaOcsp | PkiOptions.CrlEverywhere, out RevocationResponder responder, out CertificateAuthority rootAuthority, out CertificateAuthority intermediateAuthority, out X509Certificate2 serverCert, subjectName: serverName, keySize: 2048, extensions: TestHelper.BuildTlsServerCertExtensions(serverName)); SslClientAuthenticationOptions clientOpts = new SslClientAuthenticationOptions { TargetHost = serverName, RemoteCertificateValidationCallback = CertificateValidationCallback, CertificateRevocationCheckMode = revocationMode, }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { X509Certificate2 temp = new X509Certificate2(serverCert.Export(X509ContentType.Pkcs12)); serverCert.Dispose(); serverCert = temp; } await using (clientStream) await using (serverStream) using (responder) using (rootAuthority) using (intermediateAuthority) using (serverCert) using (X509Certificate2 issuerCert = intermediateAuthority.CloneIssuerCert()) await using (SslStream tlsClient = new SslStream(clientStream)) await using (SslStream tlsServer = new SslStream(serverStream)) { intermediateAuthority.Revoke(serverCert, serverCert.NotBefore); SslServerAuthenticationOptions serverOpts = new SslServerAuthenticationOptions(); if (offlineContext.HasValue) { serverOpts.ServerCertificateContext = SslStreamCertificateContext.Create( serverCert, new X509Certificate2Collection(issuerCert), offlineContext.GetValueOrDefault()); if (revocationMode == X509RevocationMode.Offline) { if (offlineContext.GetValueOrDefault(false)) { // Add a delay just to show we're not winning because of race conditions. await Task.Delay(200); } else { if (!OperatingSystem.IsLinux()) { throw new InvalidOperationException( "This test configuration uses reflection and is only defined for Linux."); } FieldInfo pendingDownloadTaskField = typeof(SslStreamCertificateContext).GetField( "_pendingDownload", BindingFlags.Instance | BindingFlags.NonPublic); if (pendingDownloadTaskField is null) { throw new InvalidOperationException("Cannot find the pending download field."); } Task download = (Task)pendingDownloadTaskField.GetValue(serverOpts.ServerCertificateContext); // If it's null, it should mean it has already finished. If not, it might not have. if (download is not null) { await download; } } } } else { serverOpts.ServerCertificate = serverCert; } Task serverTask = tlsServer.AuthenticateAsServerAsync(serverOpts); Task clientTask = tlsClient.AuthenticateAsClientAsync(clientOpts); await TestConfiguration.WhenAllOrAnyFailedWithTimeout(clientTask, serverTask); }
private async Task ConnectWithRevocation_WithCallback_Core( X509RevocationMode revocationMode, bool?offlineContext = false) { string offlinePart = offlineContext.HasValue ? offlineContext.GetValueOrDefault().ToString().ToLower() : "null"; string serverName = $"{revocationMode.ToString().ToLower()}.{offlinePart}.server.example"; (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); CertificateAuthority.BuildPrivatePki( PkiOptions.EndEntityRevocationViaOcsp | PkiOptions.CrlEverywhere, out RevocationResponder responder, out CertificateAuthority rootAuthority, out CertificateAuthority intermediateAuthority, out X509Certificate2 serverCert, subjectName: serverName, keySize: 2048, extensions: TestHelper.BuildTlsServerCertExtensions(serverName)); SslClientAuthenticationOptions clientOpts = new SslClientAuthenticationOptions { TargetHost = serverName, RemoteCertificateValidationCallback = CertificateValidationCallback, CertificateRevocationCheckMode = revocationMode, }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { X509Certificate2 temp = new X509Certificate2(serverCert.Export(X509ContentType.Pkcs12)); serverCert.Dispose(); serverCert = temp; } await using (clientStream) await using (serverStream) using (responder) using (rootAuthority) using (intermediateAuthority) using (serverCert) using (X509Certificate2 issuerCert = intermediateAuthority.CloneIssuerCert()) await using (SslStream tlsClient = new SslStream(clientStream)) await using (SslStream tlsServer = new SslStream(serverStream)) { intermediateAuthority.Revoke(serverCert, serverCert.NotBefore); SslServerAuthenticationOptions serverOpts = new SslServerAuthenticationOptions(); if (offlineContext.HasValue) { serverOpts.ServerCertificateContext = SslStreamCertificateContext.Create( serverCert, new X509Certificate2Collection(issuerCert), offlineContext.GetValueOrDefault()); if (revocationMode == X509RevocationMode.Offline) { // Give the OCSP response a better chance to finish. await Task.Delay(200); } } else { serverOpts.ServerCertificate = serverCert; } Task serverTask = tlsServer.AuthenticateAsServerAsync(serverOpts); Task clientTask = tlsClient.AuthenticateAsClientAsync(clientOpts); await TestConfiguration.WhenAllOrAnyFailedWithTimeout(clientTask, serverTask); }