Repository: netty/netty
Issue: Feature request: let one pass a SecureRandom instance when building SslContext

### Expected behavior

When spawning multiple `JdkSslContext`, it should be possible to reuse a single SecureRandom instance and save allocations.

### Actual behavior

`SslContextBuilder` won't let one pass a SecureRandom instance.
Both `JdkSslServerContext#newSSLContext` and `JdkSslClientContext#newSSLContext` pass a null random value to `SSLContext#init` that allocates a new `SecureRandom` instance.

### Steps to reproduce

### Minimal yet complete reproducer code (or URL to code)

NA

### Netty version

4.1.30

### JVM version (e.g. `java -version`)

NA

### OS version (e.g. `uname -a`)

NA


Issue comments:
@normanmaurer please let me know if I can send a PR
@slandelle I wonder if you would not be better of to just create your `SSLContext` (the java one) directly and then construct the `JdkSslContext` from it (we have a constructor that can wrap an existing `SSLContext`) ?


Oh right, I didn't notice you were keeping the `JdkSslContext` constructor public.
Yes, that would work for me, thanks!
Actually, the "full" constructor is package protected, so there's no way to force the enabled protocols.
@slandelle what about adding another public constructor that allows this ?  Also in the meantime you can also just wrap the `JdkSslContext` that you created via a `DelegatingSslContext` and override `initEngine` where you can just set the protocols etc. 
PR sent: #8389

Pull request review comments:
@slandelle do we need to call `protocols.clone()` if these are not null ?
@slandelle maybe mark this constructor as `@deprecated` ?
sure
right, that would be consistent with SslContextBuilder
@slandelle please use java docs style via `{@link ... }`
crossing fingers checkstyle won't complain on line length...



Patch that resolved the issue:
diff --git a/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java b/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java
index 2b61391b491..6aef52a246f 100644
--- a/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java
+++ b/handler/src/main/java/io/netty/handler/ssl/JdkSslContext.java
@@ -140,7 +140,10 @@ public class JdkSslContext extends SslContext {
      * @param sslContext the {@link SSLContext} to use.
      * @param isClient {@code true} if this context should create {@link SSLEngine}s for client-side usage.
      * @param clientAuth the {@link ClientAuth} to use. This will only be used when {@param isClient} is {@code false}.
+     * @deprecated Use {@link #JdkSslContext(SSLContext, boolean, Iterable, CipherSuiteFilter,
+     * ApplicationProtocolConfig, ClientAuth, String[], boolean)}
      */
+    @Deprecated
     public JdkSslContext(SSLContext sslContext, boolean isClient,
                          ClientAuth clientAuth) {
         this(sslContext, isClient, null, IdentityCipherSuiteFilter.INSTANCE,
@@ -156,11 +159,44 @@ public JdkSslContext(SSLContext sslContext, boolean isClient,
      * @param cipherFilter the filter to use.
      * @param apn the {@link ApplicationProtocolConfig} to use.
      * @param clientAuth the {@link ClientAuth} to use. This will only be used when {@param isClient} is {@code false}.
+     * @deprecated Use {@link #JdkSslContext(SSLContext, boolean, Iterable, CipherSuiteFilter,
+     * ApplicationProtocolConfig, ClientAuth, String[], boolean)}
      */
+    @Deprecated
     public JdkSslContext(SSLContext sslContext, boolean isClient, Iterable<String> ciphers,
                          CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn,
                          ClientAuth clientAuth) {
-        this(sslContext, isClient, ciphers, cipherFilter, toNegotiator(apn, !isClient), clientAuth, null, false);
+        this(sslContext, isClient, ciphers, cipherFilter, apn, clientAuth, null, false);
+    }
+
+    /**
+     * Creates a new {@link JdkSslContext} from a pre-configured {@link SSLContext}.
+     *
+     * @param sslContext the {@link SSLContext} to use.
+     * @param isClient {@code true} if this context should create {@link SSLEngine}s for client-side usage.
+     * @param ciphers the ciphers to use or {@code null} if the standard should be used.
+     * @param cipherFilter the filter to use.
+     * @param apn the {@link ApplicationProtocolConfig} to use.
+     * @param clientAuth the {@link ClientAuth} to use. This will only be used when {@param isClient} is {@code false}.
+     * @param protocols the protocols to enable, or {@code null} to enable the default protocols.
+     * @param startTls {@code true} if the first write request shouldn't be encrypted
+     */
+    public JdkSslContext(SSLContext sslContext,
+                         boolean isClient,
+                         Iterable<String> ciphers,
+                         CipherSuiteFilter cipherFilter,
+                         ApplicationProtocolConfig apn,
+                         ClientAuth clientAuth,
+                         String[] protocols,
+                         boolean startTls) {
+        this(sslContext,
+                isClient,
+                ciphers,
+                cipherFilter,
+                toNegotiator(apn, !isClient),
+                clientAuth,
+                protocols == null ? null : protocols.clone(),
+                startTls);
     }
 
     @SuppressWarnings("deprecation")


Test patch: