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