Repository: eclipse-vertx/vert.x

Problem statement:
Remove KeyCertOptions limitation for OpenSSL
The previous version of OpenSSL engine was restricted to use `pem` file format.

Now the engine can use a generic `KeyManagerFactory` : https://github.com/netty/netty/pull/5439

We can so support it.



Hints:

Patch:
diff --git a/src/main/java/io/vertx/core/net/impl/SSLHelper.java b/src/main/java/io/vertx/core/net/impl/SSLHelper.java
--- a/src/main/java/io/vertx/core/net/impl/SSLHelper.java
+++ b/src/main/java/io/vertx/core/net/impl/SSLHelper.java
@@ -33,7 +33,6 @@
 import io.vertx.core.net.NetClientOptions;
 import io.vertx.core.net.NetServerOptions;
 import io.vertx.core.net.OpenSSLEngineOptions;
-import io.vertx.core.net.PemKeyCertOptions;
 import io.vertx.core.net.SSLEngineOptions;
 import io.vertx.core.net.TCPSSLOptions;
 import io.vertx.core.net.TrustOptions;
@@ -41,7 +40,6 @@
 import javax.net.ssl.*;
 import java.io.ByteArrayInputStream;
 import java.security.KeyStore;
-import java.security.PrivateKey;
 import java.security.cert.CRL;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
@@ -242,41 +240,19 @@ private SslContext createContext(VertxInternal vertx) {
       if (client) {
         builder = SslContextBuilder.forClient();
         if (keyMgrFactory != null) {
-          if (openSsl) {
-            if (keyCertOptions instanceof PemKeyCertOptions) {
-              KeyStoreHelper.KeyCert keyStoreHelper =(KeyStoreHelper.KeyCert) KeyStoreHelper.create(vertx, keyCertOptions);
-              X509Certificate[] certs = keyStoreHelper.loadCerts();
-              PrivateKey privateKey = keyStoreHelper.loadPrivateKey();
-              builder.keyManager(privateKey, certs);
-            } else {
-              throw new VertxException("OpenSSL server key/certificate must be configured with .pem format");
-            }
-          } else {
-            builder.keyManager(keyMgrFactory);
-          }
+          builder.keyManager(keyMgrFactory);
         }
       } else {
-        if (openSsl) {
-          if (keyCertOptions instanceof PemKeyCertOptions) {
-            KeyStoreHelper.KeyCert keyStoreHelper =(KeyStoreHelper.KeyCert) KeyStoreHelper.create(vertx, keyCertOptions);
-            X509Certificate[] certs = keyStoreHelper.loadCerts();
-            PrivateKey privateKey = keyStoreHelper.loadPrivateKey();
-            builder = SslContextBuilder.forServer(privateKey, certs);
-          } else {
-            throw new VertxException("OpenSSL server key/certificate must be configured with .pem format");
-          }
-        } else {
-          if (keyMgrFactory == null) {
-            throw new VertxException("Key/certificate is mandatory for SSL");
-          }
-          builder = SslContextBuilder.forServer(keyMgrFactory);
+        if (keyMgrFactory == null) {
+          throw new VertxException("Key/certificate is mandatory for SSL");
         }
+        builder = SslContextBuilder.forServer(keyMgrFactory);
       }
       Collection<String> cipherSuites = enabledCipherSuites;
       if (openSsl) {
         builder.sslProvider(SslProvider.OPENSSL);
         if (cipherSuites == null || cipherSuites.isEmpty()) {
-          cipherSuites = OpenSsl.availableCipherSuites();
+          cipherSuites = OpenSsl.availableOpenSslCipherSuites();
         }
       } else {
         builder.sslProvider(SslProvider.JDK);
diff --git a/src/main/java/io/vertx/core/net/package-info.java b/src/main/java/io/vertx/core/net/package-info.java
--- a/src/main/java/io/vertx/core/net/package-info.java
+++ b/src/main/java/io/vertx/core/net/package-info.java
@@ -667,9 +667,6 @@
  * and use http://netty.io/wiki/forked-tomcat-native.html[netty-tcnative] jar on the classpath. Using tcnative may require
  * OpenSSL to be installed on your OS depending on the tcnative implementation.
  *
- * OpenSSL restricts the key/certificate configuration to `.pem` files. However it is still possible to use any trust
- * configuration.
- *
  * ===== Jetty-ALPN support
  *
  * Jetty-ALPN is a small jar that overrides a few classes of Java 8 distribution to support ALPN.


Test patch:
diff --git a/src/test/java/io/vertx/test/core/HttpTLSTest.java b/src/test/java/io/vertx/test/core/HttpTLSTest.java
--- a/src/test/java/io/vertx/test/core/HttpTLSTest.java
+++ b/src/test/java/io/vertx/test/core/HttpTLSTest.java
@@ -276,7 +276,19 @@ public void testTLSVerifyNonMatchingHost() throws Exception {
     testTLS(TLSCert.NONE, TLSCert.NONE, TLSCert.MIM, TLSCert.NONE).clientTrustAll().clientVerifyHost().fail();
   }
 
-    // OpenSSL tests
+  // OpenSSL tests
+
+  @Test
+  // Server uses OpenSSL with JKS
+  public void testTLSClientTrustServerCertJKSOpenSSL() throws Exception {
+    testTLS(TLSCert.NONE, TLSCert.JKS, TLSCert.JKS, TLSCert.NONE).serverOpenSSL().pass();
+  }
+
+  @Test
+  // Server uses OpenSSL with PKCS12
+  public void testTLSClientTrustServerCertPKCS12OpenSSL() throws Exception {
+    testTLS(TLSCert.NONE, TLSCert.JKS, TLSCert.PKCS12, TLSCert.NONE).serverOpenSSL().pass();
+  }
 
   @Test
   // Server uses OpenSSL with PEM
@@ -302,6 +314,24 @@ public void testTLSClientTrustServerCertWithPEMOpenSSL() throws Exception {
     testTLS(TLSCert.NONE, TLSCert.PEM, TLSCert.JKS, TLSCert.NONE).clientOpenSSL().pass();
   }
 
+  @Test
+  // Client specifies cert and it is required
+  public void testTLSClientCertRequiredOpenSSL() throws Exception {
+    testTLS(TLSCert.JKS, TLSCert.JKS, TLSCert.JKS, TLSCert.JKS).clientOpenSSL().requiresClientAuth().pass();
+  }
+
+  @Test
+  // Client specifies cert and it is required
+  public void testTLSClientCertPKCS12RequiredOpenSSL() throws Exception {
+    testTLS(TLSCert.PKCS12, TLSCert.JKS, TLSCert.JKS, TLSCert.JKS).clientOpenSSL().requiresClientAuth().pass();
+  }
+
+  @Test
+  // Client specifies cert and it is required
+  public void testTLSClientCertPEMRequiredOpenSSL() throws Exception {
+    testTLS(TLSCert.PEM, TLSCert.JKS, TLSCert.JKS, TLSCert.JKS).clientOpenSSL().requiresClientAuth().pass();
+  }
+
   class TLSTest {
 
     HttpVersion version;
@@ -563,20 +593,6 @@ public void testJKSInvalidPassword() {
     testInvalidKeyStore(((JksOptions) TLSCert.JKS.getServerKeyCertOptions()).setPassword("wrongpassword"), "Keystore was tampered with, or password was incorrect", null);
   }
 
-  @Test
-  public void testJKSOpenSSL() {
-    HttpServerOptions serverOptions = new HttpServerOptions().setOpenSslEngineOptions(new OpenSSLEngineOptions());
-    setOptions(serverOptions, TLSCert.JKS.getServerKeyCertOptions());
-    testStore(serverOptions, Collections.singletonList("OpenSSL server key/certificate must be configured with .pem format"), null);
-  }
-
-  @Test
-  public void testPKCS12OpenSSL() {
-    HttpServerOptions serverOptions = new HttpServerOptions().setOpenSslEngineOptions(new OpenSSLEngineOptions());
-    setOptions(serverOptions, TLSCert.JKS.getServerKeyCertOptions());
-    testStore(serverOptions, Collections.singletonList("OpenSSL server key/certificate must be configured with .pem format"), null);
-  }
-
   @Test
   public void testPKCS12InvalidPath() {
     testInvalidKeyStore(((PfxOptions) TLSCert.PKCS12.getServerKeyCertOptions()).setPath("/invalid.p12"), "java.nio.file.NoSuchFileException: ", "invalid.p12");