1 /*
2 * Copyright 2017 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty5.handler.ssl;
17
18 import io.netty5.util.internal.PlatformDependent;
19
20 import javax.net.ssl.SSLEngine;
21 import java.lang.invoke.MethodHandle;
22 import java.lang.invoke.MethodHandles;
23 import java.lang.invoke.MethodType;
24
25 /**
26 * Contains methods that can be used to detect if conscrypt is usable.
27 */
28 final class Conscrypt {
29 // This class exists to avoid loading other conscrypt related classes using features only available in JDK8+,
30 // because we need to maintain JDK6+ runtime compatibility.
31
32 private static final MethodHandle IS_CONSCRYPT_SSLENGINE;
33
34 static {
35 MethodHandle isConscryptSSLEngine = null;
36
37 // Only works on Java14 and earlier for now. See https://github.com/google/conscrypt/issues/838
38 if (PlatformDependent.javaVersion() < 15 || PlatformDependent.isAndroid()) {
39 try {
40 MethodHandles.Lookup lookup = MethodHandles.lookup();
41 Class<?> providerClass = Class.forName("org.conscrypt.OpenSSLProvider", true,
42 PlatformDependent.getClassLoader(ConscryptAlpnSslEngine.class));
43 lookup.findConstructor(providerClass, MethodType.methodType(void.class)).invoke();
44
45 Class<?> conscryptClass = Class.forName("org.conscrypt.Conscrypt", true,
46 PlatformDependent.getClassLoader(ConscryptAlpnSslEngine.class));
47 isConscryptSSLEngine = lookup.findStatic(conscryptClass, "isConscrypt",
48 MethodType.methodType(boolean.class, SSLEngine.class));
49 } catch (Throwable ignore) {
50 // ignore
51 }
52 }
53 IS_CONSCRYPT_SSLENGINE = isConscryptSSLEngine;
54 }
55
56 /**
57 * Indicates whether or not conscrypt is available on the current system.
58 */
59 static boolean isAvailable() {
60 return IS_CONSCRYPT_SSLENGINE != null;
61 }
62
63 /**
64 * Returns {@code true} if the passed in {@link SSLEngine} is handled by Conscrypt, {@code false} otherwise.
65 */
66 static boolean isEngineSupported(SSLEngine engine) {
67 try {
68 return IS_CONSCRYPT_SSLENGINE != null && (boolean) IS_CONSCRYPT_SSLENGINE.invokeExact(engine);
69 } catch (IllegalAccessException ignore) {
70 return false;
71 } catch (Throwable ex) {
72 throw new RuntimeException(ex);
73 }
74 }
75
76 private Conscrypt() { }
77 }