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