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