/* * Copyright 2014 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package io.netty.handler.ssl; import io.netty.buffer.ByteBufAllocator; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol; import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior; import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.crypto.Cipher; import javax.crypto.EncryptedPrivateKeyInfo; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import java.io.File; import java.io.IOException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.List; /** * A secure socket protocol implementation which acts as a factory for {@link SSLEngine} and {@link SslHandler}. * Internally, it is implemented via JDK's {@link SSLContext} or OpenSSL's {@code SSL_CTX}. * * <h3>Making your server support SSL/TLS</h3> * <pre> * // In your {@link ChannelInitializer}: * {@link ChannelPipeline} p = channel.pipeline(); * {@link SslContext} sslCtx = {@link #newServerContext(File, File) SslContext.newServerContext(...)}; * p.addLast("ssl", {@link #newEngine(ByteBufAllocator) sslCtx.newEngine(channel.alloc())}); * ... * </pre> * * <h3>Making your client support SSL/TLS</h3> * <pre> * // In your {@link ChannelInitializer}: * {@link ChannelPipeline} p = channel.pipeline(); * {@link SslContext} sslCtx = {@link #newClientContext(File) SslContext.newClientContext(...)}; * p.addLast("ssl", {@link #newEngine(ByteBufAllocator, String, int) sslCtx.newEngine(channel.alloc(), host, port)}); * ... * </pre> */ public abstract class SslContext { static final CertificateFactory X509_CERT_FACTORY; static { try { X509_CERT_FACTORY = CertificateFactory.getInstance("X.509"); } catch (CertificateException e) { throw new IllegalStateException("unable to instance X.509 CertificateFactory", e); } } /** * Returns the default server-side implementation provider currently in use. * * @return {@link SslProvider#OPENSSL} if OpenSSL is available. {@link SslProvider#JDK} otherwise. */ public static SslProvider defaultServerProvider() { return defaultProvider(); } /** * Returns the default client-side implementation provider currently in use. * * @return {@link SslProvider#OPENSSL} if OpenSSL is available. {@link SslProvider#JDK} otherwise. */ public static SslProvider defaultClientProvider() { return defaultProvider(); } private static SslProvider defaultProvider() { if (OpenSsl.isAvailable()) { return SslProvider.OPENSSL; } else { return SslProvider.JDK; } } /** * Creates a new server-side {@link SslContext}. * * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @return a new server-side {@link SslContext} */ public static SslContext newServerContext(File certChainFile, File keyFile) throws SSLException { return newServerContext(certChainFile, keyFile, null); } /** * Creates a new server-side {@link SslContext}. * * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * @return a new server-side {@link SslContext} */ public static SslContext newServerContext( File certChainFile, File keyFile, String keyPassword) throws SSLException { return newServerContext(null, certChainFile, keyFile, keyPassword); } /** * @deprecated Use the factory methods that accept {@link ApplicationProtocolConfig} instead. * * Creates a new server-side {@link SslContext}. * * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param nextProtocols the application layer protocols to accept, in the order of preference. * {@code null} to disable TLS NPN/ALPN extension. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * @return a new server-side {@link SslContext} */ @Deprecated public static SslContext newServerContext( File certChainFile, File keyFile, String keyPassword, Iterable<String> ciphers, Iterable<String> nextProtocols, long sessionCacheSize, long sessionTimeout) throws SSLException { return newServerContext( null, certChainFile, keyFile, keyPassword, ciphers, nextProtocols, sessionCacheSize, sessionTimeout); } /** * Creates a new server-side {@link SslContext}. * * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param cipherFilter a filter to apply over the supplied list of ciphers * @param apn Provides a means to configure parameters related to application protocol negotiation. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * @return a new server-side {@link SslContext} */ public static SslContext newServerContext( File certChainFile, File keyFile, String keyPassword, Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { return newServerContext( null, certChainFile, keyFile, keyPassword, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); } /** * Creates a new server-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @return a new server-side {@link SslContext} */ public static SslContext newServerContext( SslProvider provider, File certChainFile, File keyFile) throws SSLException { return newServerContext(provider, certChainFile, keyFile, null); } /** * Creates a new server-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * @return a new server-side {@link SslContext} */ public static SslContext newServerContext( SslProvider provider, File certChainFile, File keyFile, String keyPassword) throws SSLException { return newServerContext(provider, certChainFile, keyFile, keyPassword, null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0); } /** * @deprecated Use the factory methods that accept {@link ApplicationProtocolConfig} instead. * * Creates a new server-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param nextProtocols the application layer protocols to accept, in the order of preference. * {@code null} to disable TLS NPN/ALPN extension. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * @return a new server-side {@link SslContext} */ @Deprecated public static SslContext newServerContext( SslProvider provider, File certChainFile, File keyFile, String keyPassword, Iterable<String> ciphers, Iterable<String> nextProtocols, long sessionCacheSize, long sessionTimeout) throws SSLException { return newServerContext(provider, certChainFile, keyFile, keyPassword, ciphers, IdentityCipherSuiteFilter.INSTANCE, toApplicationProtocolConfig(nextProtocols), sessionCacheSize, sessionTimeout); } /** * Creates a new server-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link javax.net.ssl.TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param nextProtocols the application layer protocols to accept, in the order of preference. * {@code null} to disable TLS NPN/ALPN extension. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * @return a new server-side {@link SslContext} */ public static SslContext newServerContext( SslProvider provider, File certChainFile, File keyFile, String keyPassword, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers, Iterable<String> nextProtocols, long sessionCacheSize, long sessionTimeout) throws SSLException { return newServerContext( provider, null, trustManagerFactory, certChainFile, keyFile, keyPassword, null, ciphers, IdentityCipherSuiteFilter.INSTANCE, toApplicationProtocolConfig(nextProtocols), sessionCacheSize, sessionTimeout); } /** * Creates a new server-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param cipherFilter a filter to apply over the supplied list of ciphers * Only required if {@code provider} is {@link SslProvider#JDK} * @param apn Provides a means to configure parameters related to application protocol negotiation. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * @return a new server-side {@link SslContext} */ public static SslContext newServerContext(SslProvider provider, File certChainFile, File keyFile, String keyPassword, Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { return newServerContext(provider, null, null, certChainFile, keyFile, keyPassword, null, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); } /** * Creates a new server-side {@link SslContext}. * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param trustCertChainFile an X.509 certificate chain file in PEM format. * This provides the certificate chains used for mutual authentication. * {@code null} to use the system default * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from clients. * {@code null} to use the default or the results of parsing {@code trustCertChainFile}. * This parameter is ignored if {@code provider} is not {@link SslProvider#JDK}. * @param keyCertChainFile an X.509 certificate chain file in PEM format * @param keyFile a PKCS#8 private key file in PEM format * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link KeyManager}s * that is used to encrypt data being sent to clients. * {@code null} to use the default or the results of parsing * {@code keyCertChainFile} and {@code keyFile}. * This parameter is ignored if {@code provider} is not {@link SslProvider#JDK}. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param cipherFilter a filter to apply over the supplied list of ciphers * Only required if {@code provider} is {@link SslProvider#JDK} * @param apn Provides a means to configure parameters related to application protocol negotiation. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * @return a new server-side {@link SslContext} */ public static SslContext newServerContext( SslProvider provider, File trustCertChainFile, TrustManagerFactory trustManagerFactory, File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { if (provider == null) { provider = defaultServerProvider(); } switch (provider) { case JDK: return new JdkSslServerContext( trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword, keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); case OPENSSL: return new OpenSslServerContext( keyCertChainFile, keyFile, keyPassword, trustManagerFactory, ciphers, apn, sessionCacheSize, sessionTimeout); default: throw new Error(provider.toString()); } } /** * Creates a new client-side {@link SslContext}. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext() throws SSLException { return newClientContext(null, null, null); } /** * Creates a new client-side {@link SslContext}. * * @param certChainFile an X.509 certificate chain file in PEM format * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext(File certChainFile) throws SSLException { return newClientContext(null, certChainFile); } /** * Creates a new client-side {@link SslContext}. * * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext(TrustManagerFactory trustManagerFactory) throws SSLException { return newClientContext(null, null, trustManagerFactory); } /** * Creates a new client-side {@link SslContext}. * * @param certChainFile an X.509 certificate chain file in PEM format. * {@code null} to use the system default * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext( File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException { return newClientContext(null, certChainFile, trustManagerFactory); } /** * @deprecated Use the factory methods that accept {@link ApplicationProtocolConfig} instead. * * Creates a new client-side {@link SslContext}. * * @param certChainFile an X.509 certificate chain file in PEM format. * {@code null} to use the system default * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param nextProtocols the application layer protocols to accept, in the order of preference. * {@code null} to disable TLS NPN/ALPN extension. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * * @return a new client-side {@link SslContext} */ @Deprecated public static SslContext newClientContext( File certChainFile, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers, Iterable<String> nextProtocols, long sessionCacheSize, long sessionTimeout) throws SSLException { return newClientContext( null, certChainFile, trustManagerFactory, ciphers, nextProtocols, sessionCacheSize, sessionTimeout); } /** * Creates a new client-side {@link SslContext}. * * @param certChainFile an X.509 certificate chain file in PEM format. * {@code null} to use the system default * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param cipherFilter a filter to apply over the supplied list of ciphers * @param apn Provides a means to configure parameters related to application protocol negotiation. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext( File certChainFile, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { return newClientContext( null, certChainFile, trustManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); } /** * Creates a new client-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext(SslProvider provider) throws SSLException { return newClientContext(provider, null, null); } /** * Creates a new client-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format. * {@code null} to use the system default * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext(SslProvider provider, File certChainFile) throws SSLException { return newClientContext(provider, certChainFile, null); } /** * Creates a new client-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext( SslProvider provider, TrustManagerFactory trustManagerFactory) throws SSLException { return newClientContext(provider, null, trustManagerFactory); } /** * Creates a new client-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format. * {@code null} to use the system default * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext( SslProvider provider, File certChainFile, TrustManagerFactory trustManagerFactory) throws SSLException { return newClientContext(provider, certChainFile, trustManagerFactory, null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0); } /** * @deprecated Use the factory methods that accept {@link ApplicationProtocolConfig}. * * Creates a new client-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format. * {@code null} to use the system default * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param nextProtocols the application layer protocols to accept, in the order of preference. * {@code null} to disable TLS NPN/ALPN extension. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * * @return a new client-side {@link SslContext} */ @Deprecated public static SslContext newClientContext( SslProvider provider, File certChainFile, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers, Iterable<String> nextProtocols, long sessionCacheSize, long sessionTimeout) throws SSLException { return newClientContext( provider, certChainFile, trustManagerFactory, null, null, null, null, ciphers, IdentityCipherSuiteFilter.INSTANCE, toApplicationProtocolConfig(nextProtocols), sessionCacheSize, sessionTimeout); } /** * Creates a new client-side {@link SslContext}. * * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param certChainFile an X.509 certificate chain file in PEM format. * {@code null} to use the system default * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param cipherFilter a filter to apply over the supplied list of ciphers * @param apn Provides a means to configure parameters related to application protocol negotiation. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext( SslProvider provider, File certChainFile, TrustManagerFactory trustManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { return newClientContext( provider, certChainFile, trustManagerFactory, null, null, null, null, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); } /** * Creates a new client-side {@link SslContext}. * @param provider the {@link SslContext} implementation to use. * {@code null} to use the current default one. * @param trustCertChainFile an X.509 certificate chain file in PEM format. * {@code null} to use the system default * @param trustManagerFactory the {@link TrustManagerFactory} that provides the {@link TrustManager}s * that verifies the certificates sent from servers. * {@code null} to use the default or the results of parsing {@code trustCertChainFile}. * This parameter is ignored if {@code provider} is not {@link SslProvider#JDK}. * @param keyCertChainFile an X.509 certificate chain file in PEM format. * This provides the public key for mutual authentication. * {@code null} to use the system default * @param keyFile a PKCS#8 private key file in PEM format. * This provides the private key for mutual authentication. * {@code null} for no mutual authentication. * @param keyPassword the password of the {@code keyFile}. * {@code null} if it's not password-protected. * Ignored if {@code keyFile} is {@code null}. * @param keyManagerFactory the {@link KeyManagerFactory} that provides the {@link KeyManager}s * that is used to encrypt data being sent to servers. * {@code null} to use the default or the results of parsing * {@code keyCertChainFile} and {@code keyFile}. * This parameter is ignored if {@code provider} is not {@link SslProvider#JDK}. * @param ciphers the cipher suites to enable, in the order of preference. * {@code null} to use the default cipher suites. * @param cipherFilter a filter to apply over the supplied list of ciphers * @param apn Provides a means to configure parameters related to application protocol negotiation. * @param sessionCacheSize the size of the cache used for storing SSL session objects. * {@code 0} to use the default value. * @param sessionTimeout the timeout for the cached SSL session objects, in seconds. * {@code 0} to use the default value. * * @return a new client-side {@link SslContext} */ public static SslContext newClientContext( SslProvider provider, File trustCertChainFile, TrustManagerFactory trustManagerFactory, File keyCertChainFile, File keyFile, String keyPassword, KeyManagerFactory keyManagerFactory, Iterable<String> ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout) throws SSLException { if (provider == null) { provider = defaultClientProvider(); } switch (provider) { case JDK: return new JdkSslClientContext( trustCertChainFile, trustManagerFactory, keyCertChainFile, keyFile, keyPassword, keyManagerFactory, ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout); case OPENSSL: return new OpenSslClientContext( trustCertChainFile, trustManagerFactory, ciphers, apn, sessionCacheSize, sessionTimeout); } // Should never happen!! throw new Error(); } static ApplicationProtocolConfig toApplicationProtocolConfig(Iterable<String> nextProtocols) { ApplicationProtocolConfig apn; if (nextProtocols == null) { apn = ApplicationProtocolConfig.DISABLED; } else { apn = new ApplicationProtocolConfig( Protocol.NPN_AND_ALPN, SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL, SelectedListenerFailureBehavior.ACCEPT, nextProtocols); } return apn; } SslContext() { } /** * Returns {@code true} if and only if this context is for server-side. */ public final boolean isServer() { return !isClient(); } /** * Returns the {@code true} if and only if this context is for client-side. */ public abstract boolean isClient(); /** * Returns the list of enabled cipher suites, in the order of preference. */ public abstract List<String> cipherSuites(); /** * Returns the size of the cache used for storing SSL session objects. */ public abstract long sessionCacheSize(); /** * Returns the timeout for the cached SSL session objects, in seconds. */ public abstract long sessionTimeout(); /** * @deprecated Use {@link #applicationProtocolNegotiator()} instead. */ @Deprecated public final List<String> nextProtocols() { return applicationProtocolNegotiator().protocols(); } /** * Returns the object responsible for negotiating application layer protocols for the TLS NPN/ALPN extensions. */ public abstract ApplicationProtocolNegotiator applicationProtocolNegotiator(); /** * Creates a new {@link SSLEngine}. * * @return a new {@link SSLEngine} */ public abstract SSLEngine newEngine(ByteBufAllocator alloc); /** * Creates a new {@link SSLEngine} using advisory peer information. * * @param peerHost the non-authoritative name of the host * @param peerPort the non-authoritative port * * @return a new {@link SSLEngine} */ public abstract SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort); /** * Returns the {@link SSLSessionContext} object held by this context. */ public abstract SSLSessionContext sessionContext(); /** * Creates a new {@link SslHandler}. * * @return a new {@link SslHandler} */ public final SslHandler newHandler(ByteBufAllocator alloc) { return newHandler(newEngine(alloc)); } /** * Creates a new {@link SslHandler} with advisory peer information. * * @param peerHost the non-authoritative name of the host * @param peerPort the non-authoritative port * * @return a new {@link SslHandler} */ public final SslHandler newHandler(ByteBufAllocator alloc, String peerHost, int peerPort) { return newHandler(newEngine(alloc, peerHost, peerPort)); } private static SslHandler newHandler(SSLEngine engine) { return new SslHandler(engine); } /** * Generates a key specification for an (encrypted) private key. * * @param password characters, if {@code null} or empty an unencrypted key is assumed * @param key bytes of the DER encoded private key * * @return a key specification * * @throws IOException if parsing {@code key} fails * @throws NoSuchAlgorithmException if the algorithm used to encrypt {@code key} is unkown * @throws NoSuchPaddingException if the padding scheme specified in the decryption algorithm is unkown * @throws InvalidKeySpecException if the decryption key based on {@code password} cannot be generated * @throws InvalidKeyException if the decryption key based on {@code password} cannot be used to decrypt * {@code key} * @throws InvalidAlgorithmParameterException if decryption algorithm parameters are somehow faulty */ protected static PKCS8EncodedKeySpec generateKeySpec(char[] password, byte[] key) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException { if (password == null || password.length == 0) { return new PKCS8EncodedKeySpec(key); } EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(key); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(encryptedPrivateKeyInfo.getAlgName()); PBEKeySpec pbeKeySpec = new PBEKeySpec(password); SecretKey pbeKey = keyFactory.generateSecret(pbeKeySpec); Cipher cipher = Cipher.getInstance(encryptedPrivateKeyInfo.getAlgName()); cipher.init(Cipher.DECRYPT_MODE, pbeKey, encryptedPrivateKeyInfo.getAlgParameters()); return encryptedPrivateKeyInfo.getKeySpec(cipher); } }