1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.handler.ssl;
18
19 import io.netty.buffer.ByteBuf;
20 import io.netty.buffer.ByteBufAllocator;
21 import io.netty.buffer.UnpooledByteBufAllocator;
22 import io.netty.internal.tcnative.Buffer;
23 import io.netty.internal.tcnative.Library;
24 import io.netty.internal.tcnative.SSL;
25 import io.netty.internal.tcnative.SSLContext;
26 import io.netty.util.CharsetUtil;
27 import io.netty.util.ReferenceCountUtil;
28 import io.netty.util.ReferenceCounted;
29 import io.netty.util.internal.EmptyArrays;
30 import io.netty.util.internal.NativeLibraryLoader;
31 import io.netty.util.internal.PlatformDependent;
32 import io.netty.util.internal.StringUtil;
33 import io.netty.util.internal.SystemPropertyUtil;
34 import io.netty.util.internal.logging.InternalLogger;
35 import io.netty.util.internal.logging.InternalLoggerFactory;
36
37 import java.io.ByteArrayInputStream;
38 import java.nio.ByteBuffer;
39 import java.security.cert.CertificateException;
40 import java.security.cert.X509Certificate;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.HashSet;
46 import java.util.Iterator;
47 import java.util.LinkedHashSet;
48 import java.util.List;
49 import java.util.Set;
50
51 import static io.netty.handler.ssl.SslUtils.*;
52
53
54
55
56
57 public final class OpenSsl {
58
59 private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSsl.class);
60 private static final Throwable UNAVAILABILITY_CAUSE;
61 static final List<String> DEFAULT_CIPHERS;
62 static final Set<String> AVAILABLE_CIPHER_SUITES;
63 private static final Set<String> AVAILABLE_OPENSSL_CIPHER_SUITES;
64 private static final Set<String> AVAILABLE_JAVA_CIPHER_SUITES;
65 private static final boolean SUPPORTS_KEYMANAGER_FACTORY;
66 private static final boolean USE_KEYMANAGER_FACTORY;
67 private static final boolean SUPPORTS_OCSP;
68 private static final boolean TLSV13_SUPPORTED;
69 private static final boolean IS_BORINGSSL;
70 private static final boolean IS_AWSLC;
71 private static final Set<String> CLIENT_DEFAULT_PROTOCOLS;
72 private static final Set<String> SERVER_DEFAULT_PROTOCOLS;
73 static final Set<String> SUPPORTED_PROTOCOLS_SET;
74 static final String[] EXTRA_SUPPORTED_TLS_1_3_CIPHERS;
75 static final String EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING;
76 static final String[] NAMED_GROUPS;
77
78 static final boolean JAVAX_CERTIFICATE_CREATION_SUPPORTED;
79
80
81
82
83 private static final String[] DEFAULT_NAMED_GROUPS = { "x25519", "secp256r1", "secp384r1", "secp521r1" };
84
85 static {
86 Throwable cause = null;
87
88 if (SystemPropertyUtil.getBoolean("io.netty.handler.ssl.noOpenSsl", false)) {
89 cause = new UnsupportedOperationException(
90 "OpenSSL was explicit disabled with -Dio.netty.handler.ssl.noOpenSsl=true");
91
92 logger.debug(
93 "netty-tcnative explicit disabled; " +
94 OpenSslEngine.class.getSimpleName() + " will be unavailable.", cause);
95 } else {
96
97 try {
98 Class.forName("io.netty.internal.tcnative.SSLContext", false,
99 PlatformDependent.getClassLoader(OpenSsl.class));
100 } catch (ClassNotFoundException t) {
101 cause = t;
102 logger.debug(
103 "netty-tcnative not in the classpath; " +
104 OpenSslEngine.class.getSimpleName() + " will be unavailable.");
105 }
106
107
108 if (cause == null) {
109 try {
110
111 loadTcNative();
112 } catch (Throwable t) {
113 cause = t;
114 logger.debug(
115 "Failed to load netty-tcnative; " +
116 OpenSslEngine.class.getSimpleName() + " will be unavailable, unless the " +
117 "application has already loaded the symbols by some other means. " +
118 "See https://netty.io/wiki/forked-tomcat-native.html for more information.", t);
119 }
120
121 try {
122 String engine = SystemPropertyUtil.get("io.netty.handler.ssl.openssl.engine", null);
123 if (engine == null) {
124 logger.debug("Initialize netty-tcnative using engine: 'default'");
125 } else {
126 logger.debug("Initialize netty-tcnative using engine: '{}'", engine);
127 }
128 initializeTcNative(engine);
129
130
131
132
133 cause = null;
134 } catch (Throwable t) {
135 if (cause == null) {
136 cause = t;
137 }
138 logger.debug(
139 "Failed to initialize netty-tcnative; " +
140 OpenSslEngine.class.getSimpleName() + " will be unavailable. " +
141 "See https://netty.io/wiki/forked-tomcat-native.html for more information.", t);
142 }
143 }
144 }
145
146 UNAVAILABILITY_CAUSE = cause;
147 CLIENT_DEFAULT_PROTOCOLS = defaultProtocols("jdk.tls.client.protocols");
148 SERVER_DEFAULT_PROTOCOLS = defaultProtocols("jdk.tls.server.protocols");
149
150 if (cause == null) {
151 logger.debug("netty-tcnative using native library: {}", SSL.versionString());
152
153 final List<String> defaultCiphers = new ArrayList<String>();
154 final Set<String> availableOpenSslCipherSuites = new LinkedHashSet<String>(128);
155 boolean supportsKeyManagerFactory = false;
156 boolean useKeyManagerFactory = false;
157 boolean tlsv13Supported = false;
158 String[] namedGroups = DEFAULT_NAMED_GROUPS;
159 Set<String> defaultConvertedNamedGroups = new LinkedHashSet<String>(namedGroups.length);
160 for (int i = 0; i < namedGroups.length; i++) {
161 defaultConvertedNamedGroups.add(GroupsConverter.toOpenSsl(namedGroups[i]));
162 }
163
164 IS_BORINGSSL = "BoringSSL".equals(versionString());
165 IS_AWSLC = versionString().startsWith("AWS-LC");
166 if (IS_BORINGSSL) {
167 EXTRA_SUPPORTED_TLS_1_3_CIPHERS = new String [] { "TLS_AES_128_GCM_SHA256",
168 "TLS_AES_256_GCM_SHA384" ,
169 "TLS_CHACHA20_POLY1305_SHA256" };
170
171 StringBuilder ciphersBuilder = new StringBuilder(128);
172 for (String cipher: EXTRA_SUPPORTED_TLS_1_3_CIPHERS) {
173 ciphersBuilder.append(cipher).append(":");
174 }
175 ciphersBuilder.setLength(ciphersBuilder.length() - 1);
176 EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING = ciphersBuilder.toString();
177 } else {
178 EXTRA_SUPPORTED_TLS_1_3_CIPHERS = EmptyArrays.EMPTY_STRINGS;
179 EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING = StringUtil.EMPTY_STRING;
180 }
181
182 try {
183 final long sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
184
185
186 Iterator<String> defaultGroupsIter = defaultConvertedNamedGroups.iterator();
187 while (defaultGroupsIter.hasNext()) {
188 if (!SSLContext.setCurvesList(sslCtx, defaultGroupsIter.next())) {
189
190
191
192 defaultGroupsIter.remove();
193
194
195 SSL.clearError();
196 }
197 }
198 namedGroups = defaultConvertedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS);
199
200 long certBio = 0;
201 long keyBio = 0;
202 long cert = 0;
203 long key = 0;
204 try {
205
206
207 if (SslProvider.isTlsv13Supported(SslProvider.JDK)) {
208 try {
209 StringBuilder tlsv13Ciphers = new StringBuilder();
210
211 for (String cipher : TLSV13_CIPHERS) {
212 String converted = CipherSuiteConverter.toOpenSsl(cipher, IS_BORINGSSL);
213 if (converted != null) {
214 tlsv13Ciphers.append(converted).append(':');
215 }
216 }
217 if (tlsv13Ciphers.length() == 0) {
218 tlsv13Supported = false;
219 } else {
220 tlsv13Ciphers.setLength(tlsv13Ciphers.length() - 1);
221 SSLContext.setCipherSuite(sslCtx, tlsv13Ciphers.toString(), true);
222 tlsv13Supported = true;
223 }
224
225 } catch (Exception ignore) {
226 tlsv13Supported = false;
227 SSL.clearError();
228 }
229 }
230
231 SSLContext.setCipherSuite(sslCtx, "ALL", false);
232
233 final long ssl = SSL.newSSL(sslCtx, true);
234 try {
235 for (String c: SSL.getCiphers(ssl)) {
236
237 if (c == null || c.isEmpty() || availableOpenSslCipherSuites.contains(c) ||
238
239 !tlsv13Supported && isTLSv13Cipher(c)) {
240 continue;
241 }
242 availableOpenSslCipherSuites.add(c);
243 }
244 if (IS_BORINGSSL) {
245
246
247 Collections.addAll(availableOpenSslCipherSuites, EXTRA_SUPPORTED_TLS_1_3_CIPHERS);
248 Collections.addAll(availableOpenSslCipherSuites,
249 "AEAD-AES128-GCM-SHA256",
250 "AEAD-AES256-GCM-SHA384",
251 "AEAD-CHACHA20-POLY1305-SHA256");
252 }
253
254 PemEncoded privateKey = PemPrivateKey.valueOf(PROBING_KEY.getBytes(CharsetUtil.US_ASCII));
255 try {
256
257
258 SSLContext.setCertificateCallback(sslCtx, null);
259
260 X509Certificate certificate = selfSignedCertificate();
261 certBio = ReferenceCountedOpenSslContext.toBIO(ByteBufAllocator.DEFAULT, certificate);
262 cert = SSL.parseX509Chain(certBio);
263
264 keyBio = ReferenceCountedOpenSslContext.toBIO(
265 UnpooledByteBufAllocator.DEFAULT, privateKey.retain());
266 key = SSL.parsePrivateKey(keyBio, null);
267
268 SSL.setKeyMaterial(ssl, cert, key);
269 supportsKeyManagerFactory = true;
270 try {
271 boolean propertySet = SystemPropertyUtil.contains(
272 "io.netty.handler.ssl.openssl.useKeyManagerFactory");
273 if (!(IS_BORINGSSL || IS_AWSLC)) {
274 useKeyManagerFactory = SystemPropertyUtil.getBoolean(
275 "io.netty.handler.ssl.openssl.useKeyManagerFactory", true);
276
277 if (propertySet) {
278 logger.info("System property " +
279 "'io.netty.handler.ssl.openssl.useKeyManagerFactory'" +
280 " is deprecated and so will be ignored in the future");
281 }
282 } else {
283 useKeyManagerFactory = true;
284 if (propertySet) {
285 logger.info("System property " +
286 "'io.netty.handler.ssl.openssl.useKeyManagerFactory'" +
287 " is deprecated and will be ignored when using BoringSSL or AWS-LC");
288 }
289 }
290 } catch (Throwable ignore) {
291 logger.debug("Failed to get useKeyManagerFactory system property.");
292 }
293 } catch (Exception e) {
294 logger.debug("KeyManagerFactory not supported", e);
295 SSL.clearError();
296 } finally {
297 privateKey.release();
298 }
299 } finally {
300 SSL.freeSSL(ssl);
301 if (certBio != 0) {
302 SSL.freeBIO(certBio);
303 }
304 if (keyBio != 0) {
305 SSL.freeBIO(keyBio);
306 }
307 if (cert != 0) {
308 SSL.freeX509Chain(cert);
309 }
310 if (key != 0) {
311 SSL.freePrivateKey(key);
312 }
313 }
314
315 String groups = SystemPropertyUtil.get("jdk.tls.namedGroups", null);
316 if (groups != null) {
317 String[] nGroups = groups.split(",");
318 Set<String> supportedNamedGroups = new LinkedHashSet<String>(nGroups.length);
319 Set<String> supportedConvertedNamedGroups = new LinkedHashSet<String>(nGroups.length);
320
321 Set<String> unsupportedNamedGroups = new LinkedHashSet<String>();
322 for (String namedGroup : nGroups) {
323 String converted = GroupsConverter.toOpenSsl(namedGroup);
324 if (SSLContext.setCurvesList(sslCtx, converted)) {
325 supportedConvertedNamedGroups.add(converted);
326 supportedNamedGroups.add(namedGroup);
327 } else {
328 unsupportedNamedGroups.add(namedGroup);
329
330
331 SSL.clearError();
332 }
333 }
334
335 if (supportedNamedGroups.isEmpty()) {
336 namedGroups = defaultConvertedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS);
337 logger.info("All configured namedGroups are not supported: {}. Use default: {}.",
338 Arrays.toString(unsupportedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS)),
339 Arrays.toString(DEFAULT_NAMED_GROUPS));
340 } else {
341 String[] groupArray = supportedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS);
342 if (unsupportedNamedGroups.isEmpty()) {
343 logger.info("Using configured namedGroups -D 'jdk.tls.namedGroup': {} ",
344 Arrays.toString(groupArray));
345 } else {
346 logger.info("Using supported configured namedGroups: {}. Unsupported namedGroups: {}. ",
347 Arrays.toString(groupArray),
348 Arrays.toString(unsupportedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS)));
349 }
350 namedGroups = supportedConvertedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS);
351 }
352 } else {
353 namedGroups = defaultConvertedNamedGroups.toArray(EmptyArrays.EMPTY_STRINGS);
354 }
355 } finally {
356 SSLContext.free(sslCtx);
357 }
358 } catch (Exception e) {
359 logger.warn("Failed to get the list of available OpenSSL cipher suites.", e);
360 }
361 NAMED_GROUPS = namedGroups;
362 AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.unmodifiableSet(availableOpenSslCipherSuites);
363 final Set<String> availableJavaCipherSuites = new LinkedHashSet<String>(
364 AVAILABLE_OPENSSL_CIPHER_SUITES.size() * 2);
365 for (String cipher: AVAILABLE_OPENSSL_CIPHER_SUITES) {
366
367 if (!isTLSv13Cipher(cipher)) {
368 final String tlsConversion = CipherSuiteConverter.toJava(cipher, "TLS");
369 if (tlsConversion != null) {
370 availableJavaCipherSuites.add(tlsConversion);
371 }
372 final String sslConversion = CipherSuiteConverter.toJava(cipher, "SSL");
373 if (sslConversion != null) {
374 availableJavaCipherSuites.add(sslConversion);
375 }
376 } else {
377
378 availableJavaCipherSuites.add(cipher);
379 }
380 }
381
382 addIfSupported(availableJavaCipherSuites, defaultCiphers, DEFAULT_CIPHER_SUITES);
383 addIfSupported(availableJavaCipherSuites, defaultCiphers, TLSV13_CIPHER_SUITES);
384
385 addIfSupported(availableJavaCipherSuites, defaultCiphers, EXTRA_SUPPORTED_TLS_1_3_CIPHERS);
386
387 useFallbackCiphersIfDefaultIsEmpty(defaultCiphers, availableJavaCipherSuites);
388 DEFAULT_CIPHERS = Collections.unmodifiableList(defaultCiphers);
389
390 AVAILABLE_JAVA_CIPHER_SUITES = Collections.unmodifiableSet(availableJavaCipherSuites);
391
392 final Set<String> availableCipherSuites = new LinkedHashSet<String>(
393 AVAILABLE_OPENSSL_CIPHER_SUITES.size() + AVAILABLE_JAVA_CIPHER_SUITES.size());
394 availableCipherSuites.addAll(AVAILABLE_OPENSSL_CIPHER_SUITES);
395 availableCipherSuites.addAll(AVAILABLE_JAVA_CIPHER_SUITES);
396
397 AVAILABLE_CIPHER_SUITES = availableCipherSuites;
398 SUPPORTS_KEYMANAGER_FACTORY = supportsKeyManagerFactory;
399 USE_KEYMANAGER_FACTORY = useKeyManagerFactory;
400
401 Set<String> protocols = new LinkedHashSet<String>(6);
402
403 protocols.add(SslProtocols.SSL_v2_HELLO);
404 if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV2, SSL.SSL_OP_NO_SSLv2)) {
405 protocols.add(SslProtocols.SSL_v2);
406 }
407 if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV3, SSL.SSL_OP_NO_SSLv3)) {
408 protocols.add(SslProtocols.SSL_v3);
409 }
410 if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1, SSL.SSL_OP_NO_TLSv1)) {
411 protocols.add(SslProtocols.TLS_v1);
412 }
413 if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_1, SSL.SSL_OP_NO_TLSv1_1)) {
414 protocols.add(SslProtocols.TLS_v1_1);
415 }
416 if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_2, SSL.SSL_OP_NO_TLSv1_2)) {
417 protocols.add(SslProtocols.TLS_v1_2);
418 }
419
420
421 if (tlsv13Supported && doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_3, SSL.SSL_OP_NO_TLSv1_3)) {
422 protocols.add(SslProtocols.TLS_v1_3);
423 TLSV13_SUPPORTED = true;
424 } else {
425 TLSV13_SUPPORTED = false;
426 }
427
428 SUPPORTED_PROTOCOLS_SET = Collections.unmodifiableSet(protocols);
429 SUPPORTS_OCSP = doesSupportOcsp();
430
431 if (logger.isDebugEnabled()) {
432 logger.debug("Supported protocols (OpenSSL): {} ", SUPPORTED_PROTOCOLS_SET);
433 logger.debug("Default cipher suites (OpenSSL): {}", DEFAULT_CIPHERS);
434 }
435
436
437
438
439 boolean javaxCertificateCreationSupported;
440 try {
441 javax.security.cert.X509Certificate.getInstance(PROBING_CERT.getBytes(CharsetUtil.US_ASCII));
442 javaxCertificateCreationSupported = true;
443 } catch (javax.security.cert.CertificateException ex) {
444 javaxCertificateCreationSupported = false;
445 }
446 JAVAX_CERTIFICATE_CREATION_SUPPORTED = javaxCertificateCreationSupported;
447 } else {
448 DEFAULT_CIPHERS = Collections.emptyList();
449 AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.emptySet();
450 AVAILABLE_JAVA_CIPHER_SUITES = Collections.emptySet();
451 AVAILABLE_CIPHER_SUITES = Collections.emptySet();
452 SUPPORTS_KEYMANAGER_FACTORY = false;
453 USE_KEYMANAGER_FACTORY = false;
454 SUPPORTED_PROTOCOLS_SET = Collections.emptySet();
455 SUPPORTS_OCSP = false;
456 TLSV13_SUPPORTED = false;
457 IS_BORINGSSL = false;
458 IS_AWSLC = false;
459 EXTRA_SUPPORTED_TLS_1_3_CIPHERS = EmptyArrays.EMPTY_STRINGS;
460 EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING = StringUtil.EMPTY_STRING;
461 NAMED_GROUPS = DEFAULT_NAMED_GROUPS;
462 JAVAX_CERTIFICATE_CREATION_SUPPORTED = false;
463 }
464 }
465
466 static String checkTls13Ciphers(InternalLogger logger, String ciphers) {
467 if (IS_BORINGSSL && !ciphers.isEmpty()) {
468 assert EXTRA_SUPPORTED_TLS_1_3_CIPHERS.length > 0;
469 Set<String> boringsslTlsv13Ciphers = new HashSet<String>(EXTRA_SUPPORTED_TLS_1_3_CIPHERS.length);
470 Collections.addAll(boringsslTlsv13Ciphers, EXTRA_SUPPORTED_TLS_1_3_CIPHERS);
471 boolean ciphersNotMatch = false;
472 for (String cipher: ciphers.split(":")) {
473 if (boringsslTlsv13Ciphers.isEmpty()) {
474 ciphersNotMatch = true;
475 break;
476 }
477 if (!boringsslTlsv13Ciphers.remove(cipher) &&
478 !boringsslTlsv13Ciphers.remove(CipherSuiteConverter.toJava(cipher, "TLS"))) {
479 ciphersNotMatch = true;
480 break;
481 }
482 }
483
484
485 ciphersNotMatch |= !boringsslTlsv13Ciphers.isEmpty();
486
487 if (ciphersNotMatch) {
488 if (logger.isInfoEnabled()) {
489 StringBuilder javaCiphers = new StringBuilder(128);
490 for (String cipher : ciphers.split(":")) {
491 javaCiphers.append(CipherSuiteConverter.toJava(cipher, "TLS")).append(":");
492 }
493 javaCiphers.setLength(javaCiphers.length() - 1);
494 logger.info(
495 "BoringSSL doesn't allow to enable or disable TLSv1.3 ciphers explicitly." +
496 " Provided TLSv1.3 ciphers: '{}', default TLSv1.3 ciphers that will be used: '{}'.",
497 javaCiphers, EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING);
498 }
499 return EXTRA_SUPPORTED_TLS_1_3_CIPHERS_STRING;
500 }
501 }
502 return ciphers;
503 }
504
505 static boolean isSessionCacheSupported() {
506 return version() >= 0x10100000L;
507 }
508
509
510
511
512 static X509Certificate selfSignedCertificate() throws CertificateException {
513 return (X509Certificate) SslContext.X509_CERT_FACTORY.generateCertificate(
514 new ByteArrayInputStream(PROBING_CERT.getBytes(CharsetUtil.US_ASCII))
515 );
516 }
517
518 private static boolean doesSupportOcsp() {
519 boolean supportsOcsp = false;
520 if (version() >= 0x10002000L) {
521 long sslCtx = -1;
522 try {
523 sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_TLSV1_2, SSL.SSL_MODE_SERVER);
524 SSLContext.enableOcsp(sslCtx, false);
525 supportsOcsp = true;
526 } catch (Exception ignore) {
527
528 } finally {
529 if (sslCtx != -1) {
530 SSLContext.free(sslCtx);
531 }
532 }
533 }
534 return supportsOcsp;
535 }
536 private static boolean doesSupportProtocol(int protocol, int opt) {
537 if (opt == 0) {
538
539 return false;
540 }
541 long sslCtx = -1;
542 try {
543 sslCtx = SSLContext.make(protocol, SSL.SSL_MODE_COMBINED);
544 return true;
545 } catch (Exception ignore) {
546 return false;
547 } finally {
548 if (sslCtx != -1) {
549 SSLContext.free(sslCtx);
550 }
551 }
552 }
553
554
555
556
557
558
559 public static boolean isAvailable() {
560 return UNAVAILABILITY_CAUSE == null;
561 }
562
563
564
565
566
567
568
569 @Deprecated
570 public static boolean isAlpnSupported() {
571 return version() >= 0x10002000L;
572 }
573
574
575
576
577 public static boolean isOcspSupported() {
578 return SUPPORTS_OCSP;
579 }
580
581
582
583
584
585 public static int version() {
586 return isAvailable() ? SSL.version() : -1;
587 }
588
589
590
591
592
593 public static String versionString() {
594 return isAvailable() ? SSL.versionString() : null;
595 }
596
597
598
599
600
601
602
603 public static void ensureAvailability() {
604 if (UNAVAILABILITY_CAUSE != null) {
605 throw (Error) new UnsatisfiedLinkError(
606 "failed to load the required native library").initCause(UNAVAILABILITY_CAUSE);
607 }
608 }
609
610
611
612
613
614
615
616 public static Throwable unavailabilityCause() {
617 return UNAVAILABILITY_CAUSE;
618 }
619
620
621
622
623 @Deprecated
624 public static Set<String> availableCipherSuites() {
625 return availableOpenSslCipherSuites();
626 }
627
628
629
630
631
632 public static Set<String> availableOpenSslCipherSuites() {
633 return AVAILABLE_OPENSSL_CIPHER_SUITES;
634 }
635
636
637
638
639
640 public static Set<String> availableJavaCipherSuites() {
641 return AVAILABLE_JAVA_CIPHER_SUITES;
642 }
643
644
645
646
647
648 public static boolean isCipherSuiteAvailable(String cipherSuite) {
649 String converted = CipherSuiteConverter.toOpenSsl(cipherSuite, IS_BORINGSSL);
650 if (converted != null) {
651 cipherSuite = converted;
652 }
653 return AVAILABLE_OPENSSL_CIPHER_SUITES.contains(cipherSuite);
654 }
655
656
657
658
659 public static boolean supportsKeyManagerFactory() {
660 return SUPPORTS_KEYMANAGER_FACTORY;
661 }
662
663
664
665
666
667
668
669 @Deprecated
670 public static boolean supportsHostnameValidation() {
671 return isAvailable();
672 }
673
674 static boolean useKeyManagerFactory() {
675 return USE_KEYMANAGER_FACTORY;
676 }
677
678 static long memoryAddress(ByteBuf buf) {
679 assert buf.isDirect();
680 if (buf.hasMemoryAddress()) {
681 return buf.memoryAddress();
682 }
683
684
685
686 ByteBuffer byteBuffer = buf.internalNioBuffer(0, buf.readableBytes());
687 return Buffer.address(byteBuffer) + byteBuffer.position();
688 }
689
690 private OpenSsl() { }
691
692 private static void loadTcNative() throws Exception {
693 String os = PlatformDependent.normalizedOs();
694 String arch = PlatformDependent.normalizedArch();
695
696 Set<String> libNames = new LinkedHashSet<String>(5);
697 String staticLibName = "netty_tcnative";
698
699
700
701 if ("linux".equals(os)) {
702 Set<String> classifiers = PlatformDependent.normalizedLinuxClassifiers();
703 for (String classifier : classifiers) {
704 libNames.add(staticLibName + "_" + os + '_' + arch + "_" + classifier);
705 }
706
707 libNames.add(staticLibName + "_" + os + '_' + arch);
708
709
710
711
712 libNames.add(staticLibName + "_" + os + '_' + arch + "_fedora");
713 } else {
714 libNames.add(staticLibName + "_" + os + '_' + arch);
715 }
716 libNames.add(staticLibName + "_" + arch);
717 libNames.add(staticLibName);
718
719 NativeLibraryLoader.loadFirstAvailable(PlatformDependent.getClassLoader(SSLContext.class),
720 libNames.toArray(EmptyArrays.EMPTY_STRINGS));
721 }
722
723 private static boolean initializeTcNative(String engine) throws Exception {
724 return Library.initialize("provided", engine);
725 }
726
727 static void releaseIfNeeded(ReferenceCounted counted) {
728 if (counted.refCnt() > 0) {
729 ReferenceCountUtil.safeRelease(counted);
730 }
731 }
732
733 static boolean isTlsv13Supported() {
734 return TLSV13_SUPPORTED;
735 }
736
737 static boolean isOptionSupported(SslContextOption<?> option) {
738 if (isAvailable()) {
739 if (option == OpenSslContextOption.USE_TASKS ||
740 option == OpenSslContextOption.TMP_DH_KEYLENGTH) {
741 return true;
742 }
743
744 if (isBoringSSL() || isAWSLC()) {
745 return option == OpenSslContextOption.ASYNC_PRIVATE_KEY_METHOD ||
746 option == OpenSslContextOption.PRIVATE_KEY_METHOD ||
747 option == OpenSslContextOption.CERTIFICATE_COMPRESSION_ALGORITHMS ||
748 option == OpenSslContextOption.TLS_FALSE_START ||
749 option == OpenSslContextOption.MAX_CERTIFICATE_LIST_BYTES;
750 }
751 }
752 return false;
753 }
754
755 private static Set<String> defaultProtocols(String property) {
756 String protocolsString = SystemPropertyUtil.get(property, null);
757 Set<String> protocols = new HashSet<String>();
758 if (protocolsString != null) {
759 for (String proto : protocolsString.split(",")) {
760 String p = proto.trim();
761 protocols.add(p);
762 }
763 } else {
764 protocols.add(SslProtocols.TLS_v1_2);
765 protocols.add(SslProtocols.TLS_v1_3);
766 }
767 return protocols;
768 }
769
770 static String[] defaultProtocols(boolean isClient) {
771 final Collection<String> defaultProtocols = isClient ? CLIENT_DEFAULT_PROTOCOLS : SERVER_DEFAULT_PROTOCOLS;
772 assert defaultProtocols != null;
773 List<String> protocols = new ArrayList<String>(defaultProtocols.size());
774 for (String proto : defaultProtocols) {
775 if (SUPPORTED_PROTOCOLS_SET.contains(proto)) {
776 protocols.add(proto);
777 }
778 }
779 return protocols.toArray(EmptyArrays.EMPTY_STRINGS);
780 }
781
782 static boolean isBoringSSL() {
783 return IS_BORINGSSL;
784 }
785
786 static boolean isAWSLC() {
787 return IS_AWSLC;
788 }
789 }