• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.conscrypt;
17 
18 import static io.netty.handler.ssl.SslProvider.OPENSSL;
19 import static io.netty.handler.ssl.SslProvider.OPENSSL_REFCNT;
20 import static org.conscrypt.TestUtils.initClientSslContext;
21 import static org.conscrypt.TestUtils.initServerSslContext;
22 
23 import io.netty.buffer.PooledByteBufAllocator;
24 import io.netty.handler.ssl.ApplicationProtocolConfig;
25 import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
26 import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
27 import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
28 import io.netty.handler.ssl.ApplicationProtocolNames;
29 import io.netty.handler.ssl.SslContext;
30 import io.netty.handler.ssl.SslContextBuilder;
31 import io.netty.util.ReferenceCountUtil;
32 import java.security.KeyStore.PrivateKeyEntry;
33 import java.security.NoSuchAlgorithmException;
34 import java.security.cert.X509Certificate;
35 import javax.net.ssl.SSLContext;
36 import javax.net.ssl.SSLEngine;
37 import javax.net.ssl.SSLException;
38 import org.conscrypt.java.security.TestKeyStore;
39 
40 final class OpenJdkEngineFactoryConfig {
OpenJdkEngineFactoryConfig()41     private OpenJdkEngineFactoryConfig() {}
42 
43     static final ApplicationProtocolConfig NETTY_ALPN_CONFIG =
44             new ApplicationProtocolConfig(Protocol.ALPN, SelectorFailureBehavior.NO_ADVERTISE,
45                     SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2);
46     static final String PROTOCOL = "TLSv1.2";
47 }
48 
49 /**
50  * Enumeration of various types of engines for use with engine-based benchmarks.
51  */
52 @SuppressWarnings({"ImmutableEnumChecker", "unused"})
53 public enum OpenJdkEngineFactory implements EngineFactory {
54     JDK {
55         private final SSLContext clientContext = initClientSslContext(newContext());
56         private final SSLContext serverContext = initServerSslContext(newContext());
57 
58         @Override
newClientEngine(String cipher, boolean useAlpn)59         public SSLEngine newClientEngine(String cipher, boolean useAlpn) {
60             if (useAlpn) {
61                 throw new UnsupportedOperationException("ALPN not supported for JDK");
62             }
63             return initEngine(clientContext.createSSLEngine(), cipher, true);
64         }
65 
66         @Override
newServerEngine(String cipher, boolean useAlpn)67         public SSLEngine newServerEngine(String cipher, boolean useAlpn) {
68             if (useAlpn) {
69                 throw new UnsupportedOperationException("ALPN not supported for JDK");
70             }
71             return initEngine(serverContext.createSSLEngine(), cipher, false);
72         }
73 
newContext()74         private SSLContext newContext() {
75             try {
76                 return SSLContext.getInstance(OpenJdkEngineFactoryConfig.PROTOCOL);
77             } catch (NoSuchAlgorithmException e) {
78                 throw new RuntimeException(e);
79             }
80         }
81     },
82     CONSCRYPT_UNPOOLED {
83         private final SSLContext clientContext = newConscryptClientContext();
84         private final SSLContext serverContext = newConscryptServerContext();
85 
86         @Override
newClientEngine(String cipher, boolean useAlpn)87         public SSLEngine newClientEngine(String cipher, boolean useAlpn) {
88             SSLEngine engine = initEngine(clientContext.createSSLEngine(), cipher, true);
89             if (useAlpn) {
90                 Conscrypt.setApplicationProtocols(engine, new String[] {ApplicationProtocolNames.HTTP_2});
91             }
92             return engine;
93         }
94 
95         @Override
newServerEngine(String cipher, boolean useAlpn)96         public SSLEngine newServerEngine(String cipher, boolean useAlpn) {
97             SSLEngine engine = initEngine(serverContext.createSSLEngine(), cipher, false);
98             if (useAlpn) {
99                 Conscrypt.setApplicationProtocols(engine, new String[] {ApplicationProtocolNames.HTTP_2});
100             }
101             return engine;
102         }
103 
newContext()104         private SSLContext newContext() {
105             try {
106                 return SSLContext.getInstance(
107                         OpenJdkEngineFactoryConfig.PROTOCOL, new OpenSSLProvider());
108             } catch (NoSuchAlgorithmException e) {
109                 throw new RuntimeException(e);
110             }
111         }
112     },
113     CONSCRYPT_POOLED {
114         private final SSLContext clientContext = newConscryptClientContext();
115         private final SSLContext serverContext = newConscryptServerContext();
116 
117         @Override
newClientEngine(String cipher, boolean useAlpn)118         public SSLEngine newClientEngine(String cipher, boolean useAlpn) {
119             SSLEngine engine = initEngine(clientContext.createSSLEngine(), cipher, true);
120             Conscrypt.setBufferAllocator(engine, NettyBufferAllocator.getInstance());
121             if (useAlpn) {
122                 Conscrypt.setApplicationProtocols(engine, new String[] {ApplicationProtocolNames.HTTP_2});
123             }
124             return engine;
125         }
126 
127         @Override
newServerEngine(String cipher, boolean useAlpn)128         public SSLEngine newServerEngine(String cipher, boolean useAlpn) {
129             SSLEngine engine = initEngine(serverContext.createSSLEngine(), cipher, false);
130             Conscrypt.setBufferAllocator(engine, NettyBufferAllocator.getInstance());
131             if (useAlpn) {
132                 Conscrypt.setApplicationProtocols(engine, new String[] {ApplicationProtocolNames.HTTP_2});
133             }
134             return engine;
135         }
136 
newContext()137         private SSLContext newContext() {
138             try {
139                 return SSLContext.getInstance(
140                         OpenJdkEngineFactoryConfig.PROTOCOL, new OpenSSLProvider());
141             } catch (NoSuchAlgorithmException e) {
142                 throw new RuntimeException(e);
143             }
144         }
145     },
146     NETTY {
147         private final SslContext clientContext = newNettyClientContext(OPENSSL, false);
148         private final SslContext clientContextAlpn = newNettyClientContext(OPENSSL, true);
149         private final SslContext serverContext = newNettyServerContext(OPENSSL, false);
150         private final SslContext serverContextAlpn = newNettyServerContext(OPENSSL, true);
151 
152         @Override
newClientEngine(String cipher, boolean useAlpn)153         public SSLEngine newClientEngine(String cipher, boolean useAlpn) {
154             return initEngine(
155                     clientContext(useAlpn).newEngine(PooledByteBufAllocator.DEFAULT), cipher, true);
156         }
157 
158         @Override
newServerEngine(String cipher, boolean useAlpn)159         public SSLEngine newServerEngine(String cipher, boolean useAlpn) {
160             return initEngine(serverContext(useAlpn).newEngine(PooledByteBufAllocator.DEFAULT),
161                     cipher, false);
162         }
163 
clientContext(boolean useAlpn)164         private SslContext clientContext(boolean useAlpn) {
165             return useAlpn ? clientContextAlpn : clientContext;
166         }
167 
serverContext(boolean useAlpn)168         private SslContext serverContext(boolean useAlpn) {
169             return useAlpn ? serverContextAlpn : serverContext;
170         }
171 
172         @Override
dispose(SSLEngine engine)173         public void dispose(SSLEngine engine) {
174             super.dispose(engine);
175             ReferenceCountUtil.release(engine);
176         }
177     },
178     NETTY_REF_CNT {
179         private final SslContext clientContext = newNettyClientContext(OPENSSL_REFCNT, false);
180         private final SslContext clientContextAlpn = newNettyClientContext(OPENSSL_REFCNT, true);
181         private final SslContext serverContext = newNettyServerContext(OPENSSL_REFCNT, false);
182         private final SslContext serverContextAlpn = newNettyServerContext(OPENSSL_REFCNT, true);
183 
184         @Override
newClientEngine(String cipher, boolean useAlpn)185         public SSLEngine newClientEngine(String cipher, boolean useAlpn) {
186             return initEngine(
187                     clientContext(useAlpn).newEngine(PooledByteBufAllocator.DEFAULT), cipher, true);
188         }
189 
190         @Override
newServerEngine(String cipher, boolean useAlpn)191         public SSLEngine newServerEngine(String cipher, boolean useAlpn) {
192             return initEngine(serverContext(useAlpn).newEngine(PooledByteBufAllocator.DEFAULT),
193                     cipher, false);
194         }
195 
196         @Override
dispose(SSLEngine engine)197         public void dispose(SSLEngine engine) {
198             super.dispose(engine);
199             ReferenceCountUtil.release(engine);
200         }
201 
clientContext(boolean useAlpn)202         private SslContext clientContext(boolean useAlpn) {
203             return useAlpn ? clientContextAlpn : clientContext;
204         }
205 
serverContext(boolean useAlpn)206         private SslContext serverContext(boolean useAlpn) {
207             return useAlpn ? serverContextAlpn : serverContext;
208         }
209     };
210 
211     @Override
dispose(SSLEngine engine)212     public void dispose(SSLEngine engine) {
213         engine.closeOutbound();
214     }
215 
newConscryptClientContext()216     private static SSLContext newConscryptClientContext() {
217         return TestUtils.newClientSslContext(TestUtils.getConscryptProvider());
218     }
219 
newConscryptServerContext()220     private static SSLContext newConscryptServerContext() {
221         return TestUtils.newServerSslContext(TestUtils.getConscryptProvider());
222     }
223 
newNettyClientContext( io.netty.handler.ssl.SslProvider sslProvider, boolean useAlpn)224     private static SslContext newNettyClientContext(
225             io.netty.handler.ssl.SslProvider sslProvider, boolean useAlpn) {
226         try {
227             TestKeyStore server = TestKeyStore.getServer();
228             SslContextBuilder ctx =
229                     SslContextBuilder.forClient()
230                             .sslProvider(sslProvider)
231                             .trustManager((X509Certificate[]) server.getPrivateKey("RSA", "RSA")
232                                                   .getCertificateChain());
233             if (useAlpn) {
234                 ctx.applicationProtocolConfig(OpenJdkEngineFactoryConfig.NETTY_ALPN_CONFIG);
235             }
236             return ctx.build();
237         } catch (SSLException e) {
238             throw new RuntimeException(e);
239         }
240     }
241 
newNettyServerContext( io.netty.handler.ssl.SslProvider sslProvider, boolean useAlpn)242     private static SslContext newNettyServerContext(
243             io.netty.handler.ssl.SslProvider sslProvider, boolean useAlpn) {
244         try {
245             PrivateKeyEntry server = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
246             SslContextBuilder ctx =
247                     SslContextBuilder
248                             .forServer(server.getPrivateKey(),
249                                     (X509Certificate[]) server.getCertificateChain())
250                             .sslProvider(sslProvider);
251             if (useAlpn) {
252                 ctx.applicationProtocolConfig(OpenJdkEngineFactoryConfig.NETTY_ALPN_CONFIG);
253             }
254             return ctx.build();
255         } catch (SSLException e) {
256             throw new RuntimeException(e);
257         }
258     }
259 
initEngine(SSLEngine engine, String cipher, boolean client)260     static SSLEngine initEngine(SSLEngine engine, String cipher, boolean client) {
261         engine.setEnabledProtocols(new String[]{OpenJdkEngineFactoryConfig.PROTOCOL});
262         engine.setEnabledCipherSuites(new String[] {cipher});
263         engine.setUseClientMode(client);
264         return engine;
265     }
266 }
267