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