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