From f17c68ce4a0b4f5c3131f4e4626a5a55b7f2f61f Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Tue, 17 May 2022 21:39:11 +0000 Subject: [PATCH] 8283577: SSLEngine.unwrap on read-only input ByteBuffer Reviewed-by: wetmore --- .../classes/javax/net/ssl/SSLEngine.java | 4 +- .../classes/sun/security/ssl/SSLCipher.java | 258 +++++++++++------- .../ssl/SSLCipher/ReadOnlyEngine.java | 213 +++++++++++++++ 3 files changed, 373 insertions(+), 102 deletions(-) create mode 100644 test/jdk/sun/security/ssl/SSLCipher/ReadOnlyEngine.java diff --git a/src/java.base/share/classes/javax/net/ssl/SSLEngine.java b/src/java.base/share/classes/javax/net/ssl/SSLEngine.java index 6aa64eb4598..9a74c69f9f5 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLEngine.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLEngine.java @@ -755,8 +755,8 @@ public abstract class SSLEngine { * The underlying memory used by the {@code src} and * {@code dsts ByteBuffer}s must not be the same. *

- * The inbound network buffer may be modified as a result of this - * call: therefore if the network data packet is required for some + * The inbound network buffer, {@code src}, may be modified as a result of + * this call: therefore if the network data packet is required for some * secondary purpose, the data should be duplicated before calling this * method. Note: the network data will not be useful to a second * SSLEngine, as each SSLEngine contains unique random state which diff --git a/src/java.base/share/classes/sun/security/ssl/SSLCipher.java b/src/java.base/share/classes/sun/security/ssl/SSLCipher.java index d44fb11014e..d2346c0efe9 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLCipher.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,16 @@ package sun.security.ssl; +import sun.security.ssl.Authenticator.MAC; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.IvParameterSpec; import java.nio.ByteBuffer; import java.security.AccessController; import java.security.GeneralSecurityException; @@ -41,17 +51,17 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Locale; import java.util.Map; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.ShortBufferException; -import javax.crypto.spec.GCMParameterSpec; -import javax.crypto.spec.IvParameterSpec; -import sun.security.ssl.Authenticator.MAC; -import static sun.security.ssl.CipherType.*; -import static sun.security.ssl.JsseJce.*; + +import static sun.security.ssl.CipherType.AEAD_CIPHER; +import static sun.security.ssl.CipherType.BLOCK_CIPHER; +import static sun.security.ssl.CipherType.NULL_CIPHER; +import static sun.security.ssl.CipherType.STREAM_CIPHER; +import static sun.security.ssl.JsseJce.CIPHER_3DES; +import static sun.security.ssl.JsseJce.CIPHER_AES; +import static sun.security.ssl.JsseJce.CIPHER_AES_GCM; +import static sun.security.ssl.JsseJce.CIPHER_CHACHA20_POLY1305; +import static sun.security.ssl.JsseJce.CIPHER_DES; +import static sun.security.ssl.JsseJce.CIPHER_RC4; enum SSLCipher { // exportable ciphers @@ -881,39 +891,45 @@ enum SSLCipher { public Plaintext decrypt(byte contentType, ByteBuffer bb, byte[] sequence) throws GeneralSecurityException { int len = bb.remaining(); - int pos = bb.position(); - ByteBuffer dup = bb.duplicate(); + int pos; + ByteBuffer pt; + + // Do in-place with the bb buffer if it's not read-only + if (!bb.isReadOnly()) { + pt = bb.duplicate(); + pos = bb.position(); + } else { + pt = ByteBuffer.allocate(bb.remaining()); + pos = 0; + } + try { - if (len != cipher.update(dup, bb)) { + if (len != cipher.update(bb, pt)) { // catch BouncyCastle buffering error throw new RuntimeException( "Unexpected number of plaintext bytes"); } - if (bb.position() != dup.position()) { - throw new RuntimeException( - "Unexpected ByteBuffer position"); - } } catch (ShortBufferException sbe) { // catch BouncyCastle buffering error throw new RuntimeException("Cipher buffering error in " + "JCE provider " + cipher.getProvider().getName(), sbe); } - bb.position(pos); + pt.position(pos); if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { SSLLogger.fine( - "Plaintext after DECRYPTION", bb.duplicate()); + "Plaintext after DECRYPTION", pt.duplicate()); } MAC signer = (MAC)authenticator; if (signer.macAlg().size != 0) { - checkStreamMac(signer, bb, contentType, sequence); + checkStreamMac(signer, pt, contentType, sequence); } else { authenticator.increaseSequenceNumber(); } return new Plaintext(contentType, ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, - -1, -1L, bb.slice()); + -1, -1L, pt.slice()); } @Override @@ -1059,26 +1075,30 @@ enum SSLCipher { int cipheredLength = bb.remaining(); int tagLen = signer.macAlg().size; if (tagLen != 0) { - if (!sanityCheck(tagLen, bb.remaining())) { + if (!sanityCheck(tagLen, cipheredLength)) { reservedBPE = new BadPaddingException( "ciphertext sanity check failed"); } } // decryption - int len = bb.remaining(); - int pos = bb.position(); - ByteBuffer dup = bb.duplicate(); + ByteBuffer pt; + int pos; + + // Do in-place with the bb buffer if it's not read-only + if (!bb.isReadOnly()) { + pt = bb.duplicate(); + pos = bb.position(); + } else { + pt = ByteBuffer.allocate(cipheredLength); + pos = 0; + } + try { - if (len != cipher.update(dup, bb)) { + if (cipheredLength != cipher.update(bb, pt)) { // catch BouncyCastle buffering error throw new RuntimeException( "Unexpected number of plaintext bytes"); } - - if (bb.position() != dup.position()) { - throw new RuntimeException( - "Unexpected ByteBuffer position"); - } } catch (ShortBufferException sbe) { // catch BouncyCastle buffering error throw new RuntimeException("Cipher buffering error in " + @@ -1088,14 +1108,14 @@ enum SSLCipher { if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { SSLLogger.fine( "Padded plaintext after DECRYPTION", - bb.duplicate().position(pos)); + pt.duplicate().position(pos)); } // remove the block padding - int blockSize = cipher.getBlockSize(); - bb.position(pos); + pt.position(pos); try { - removePadding(bb, tagLen, blockSize, protocolVersion); + removePadding(pt, tagLen, cipher.getBlockSize(), + protocolVersion); } catch (BadPaddingException bpe) { if (reservedBPE == null) { reservedBPE = bpe; @@ -1106,7 +1126,7 @@ enum SSLCipher { // block cipher suites. try { if (tagLen != 0) { - checkCBCMac(signer, bb, + checkCBCMac(signer, pt, contentType, cipheredLength, sequence); } else { authenticator.increaseSequenceNumber(); @@ -1124,7 +1144,7 @@ enum SSLCipher { return new Plaintext(contentType, ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, - -1, -1L, bb.slice()); + -1, -1L, pt.slice()); } @Override @@ -1330,27 +1350,31 @@ enum SSLCipher { int cipheredLength = bb.remaining(); int tagLen = signer.macAlg().size; if (tagLen != 0) { - if (!sanityCheck(tagLen, bb.remaining())) { + if (!sanityCheck(tagLen, cipheredLength)) { reservedBPE = new BadPaddingException( "ciphertext sanity check failed"); } } // decryption - int len = bb.remaining(); - int pos = bb.position(); - ByteBuffer dup = bb.duplicate(); + ByteBuffer pt; + int pos; + + // Do in-place with the bb buffer if it's not read-only + if (!bb.isReadOnly()) { + pt = bb.duplicate(); + pos = bb.position(); + } else { + pt = ByteBuffer.allocate(cipheredLength); + pos = 0; + } + try { - if (len != cipher.update(dup, bb)) { + if (cipheredLength != cipher.update(bb, pt)) { // catch BouncyCastle buffering error throw new RuntimeException( "Unexpected number of plaintext bytes"); } - - if (bb.position() != dup.position()) { - throw new RuntimeException( - "Unexpected ByteBuffer position"); - } } catch (ShortBufferException sbe) { // catch BouncyCastle buffering error throw new RuntimeException("Cipher buffering error in " + @@ -1358,20 +1382,18 @@ enum SSLCipher { } if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { - SSLLogger.fine( - "Padded plaintext after DECRYPTION", - bb.duplicate().position(pos)); + SSLLogger.fine("Padded plaintext after DECRYPTION", + pt.duplicate().position(pos)); } // Ignore the explicit nonce. - bb.position(pos + cipher.getBlockSize()); - pos = bb.position(); + int blockSize = cipher.getBlockSize(); + pos += blockSize; + pt.position(pos); // remove the block padding - int blockSize = cipher.getBlockSize(); - bb.position(pos); try { - removePadding(bb, tagLen, blockSize, protocolVersion); + removePadding(pt, tagLen, blockSize, protocolVersion); } catch (BadPaddingException bpe) { if (reservedBPE == null) { reservedBPE = bpe; @@ -1382,7 +1404,7 @@ enum SSLCipher { // block cipher suites. try { if (tagLen != 0) { - checkCBCMac(signer, bb, + checkCBCMac(signer, pt, contentType, cipheredLength, sequence); } else { authenticator.increaseSequenceNumber(); @@ -1400,7 +1422,7 @@ enum SSLCipher { return new Plaintext(contentType, ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, - -1, -1L, bb.slice()); + -1, -1L, pt.slice()); } @Override @@ -1655,10 +1677,20 @@ enum SSLCipher { // DON'T decrypt the nonce_explicit for AEAD mode. The buffer // position has moved out of the nonce_explicit range. - int len, pos = bb.position(); - ByteBuffer dup = bb.duplicate(); + ByteBuffer pt; + int len, pos; + + // Do in-place with the bb buffer if it's not read-only + if (!bb.isReadOnly()) { + pt = bb.duplicate(); + pos = bb.position(); + } else { + pt = ByteBuffer.allocate(bb.remaining()); + pos = 0; + } + try { - len = cipher.doFinal(dup, bb); + len = cipher.doFinal(bb, pt); } catch (IllegalBlockSizeException ibse) { // unlikely to happen throw new RuntimeException( @@ -1670,17 +1702,17 @@ enum SSLCipher { "JCE provider " + cipher.getProvider().getName(), sbe); } // reset the limit to the end of the decrypted data - bb.position(pos); - bb.limit(pos + len); + pt.position(pos); + pt.limit(pos + len); if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { SSLLogger.fine( - "Plaintext after DECRYPTION", bb.duplicate()); + "Plaintext after DECRYPTION", pt.duplicate()); } return new Plaintext(contentType, ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, - -1, -1L, bb.slice()); + -1, -1L, pt.slice()); } @Override @@ -1922,17 +1954,26 @@ enum SSLCipher { throw new RuntimeException( "invalid key or spec in GCM mode", ikae); } - // Update the additional authentication data, using the // implicit sequence number of the authenticator. byte[] aad = authenticator.acquireAuthenticationBytes( contentType, bb.remaining(), sn); cipher.updateAAD(aad); - int len, pos = bb.position(); - ByteBuffer dup = bb.duplicate(); + ByteBuffer pt; + int len, pos; + + // Do in-place with the bb buffer if it's not read-only + if (!bb.isReadOnly()) { + pt = bb.duplicate(); + pos = bb.position(); + } else { + pt = ByteBuffer.allocate(bb.remaining()); + pos = 0; + } + try { - len = cipher.doFinal(dup, bb); + len = cipher.doFinal(bb, pt); } catch (IllegalBlockSizeException ibse) { // unlikely to happen throw new RuntimeException( @@ -1944,24 +1985,23 @@ enum SSLCipher { "JCE provider " + cipher.getProvider().getName(), sbe); } // reset the limit to the end of the decrypted data - bb.position(pos); - bb.limit(pos + len); + pt.position(pos); + pt.limit(pos + len); // remove inner plaintext padding - int i = bb.limit() - 1; - for (; i > 0 && bb.get(i) == 0; i--) { - // blank - } + int i = pt.limit() - 1; + for (; i > 0 && pt.get(i) == 0; i--); + if (i < (pos + 1)) { throw new BadPaddingException( "Incorrect inner plaintext: no content type"); } - contentType = bb.get(i); - bb.limit(i); + contentType = pt.get(i); + pt.limit(i); if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { SSLLogger.fine( - "Plaintext after DECRYPTION", bb.duplicate()); + "Plaintext after DECRYPTION", pt.duplicate()); } if (keyLimitEnabled) { keyLimitCountdown -= len; @@ -1969,7 +2009,7 @@ enum SSLCipher { return new Plaintext(contentType, ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, - -1, -1L, bb.slice()); + -1, -1L, pt.slice()); } @Override @@ -2203,11 +2243,20 @@ enum SSLCipher { // DON'T decrypt the nonce_explicit for AEAD mode. The buffer // position has moved out of the nonce_explicit range. - int len; - int pos = bb.position(); - ByteBuffer dup = bb.duplicate(); + ByteBuffer pt; + int len, pos; + + // Do in-place with the bb buffer if it's not read-only + if (!bb.isReadOnly()) { + pt = bb.duplicate(); + pos = bb.position(); + } else { + pt = ByteBuffer.allocate(bb.remaining()); + pos = 0; + } + try { - len = cipher.doFinal(dup, bb); + len = cipher.doFinal(bb, pt); } catch (IllegalBlockSizeException ibse) { // unlikely to happen throw new RuntimeException( @@ -2219,17 +2268,17 @@ enum SSLCipher { "JCE provider " + cipher.getProvider().getName(), sbe); } // reset the limit to the end of the decrypted data - bb.position(pos); - bb.limit(pos + len); + pt.position(pos); + pt.limit(pos + len); if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { SSLLogger.fine( - "Plaintext after DECRYPTION", bb.duplicate()); + "Plaintext after DECRYPTION", pt.duplicate()); } return new Plaintext(contentType, ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, - -1, -1L, bb.slice()); + -1, -1L, pt.slice()); } @Override @@ -2473,11 +2522,20 @@ enum SSLCipher { contentType, bb.remaining(), sn); cipher.updateAAD(aad); - int len; - int pos = bb.position(); - ByteBuffer dup = bb.duplicate(); + ByteBuffer pt; + int len, pos; + + // Do in-place with the bb buffer if it's not read-only + if (!bb.isReadOnly()) { + pt = bb.duplicate(); + pos = bb.position(); + } else { + pt = ByteBuffer.allocate(bb.remaining()); + pos = 0; + } + try { - len = cipher.doFinal(dup, bb); + len = cipher.doFinal(bb, pt); } catch (IllegalBlockSizeException ibse) { // unlikely to happen throw new RuntimeException( @@ -2489,29 +2547,29 @@ enum SSLCipher { "JCE provider " + cipher.getProvider().getName(), sbe); } // reset the limit to the end of the decrypted data - bb.position(pos); - bb.limit(pos + len); + pt.position(pos); + pt.limit(pos + len); // remove inner plaintext padding - int i = bb.limit() - 1; - for (; i > 0 && bb.get(i) == 0; i--) { + int i = pt.limit() - 1; + for (; i > 0 && pt.get(i) == 0; i--) { // blank } if (i < (pos + 1)) { throw new BadPaddingException( "Incorrect inner plaintext: no content type"); } - contentType = bb.get(i); - bb.limit(i); + contentType = pt.get(i); + pt.limit(i); if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) { SSLLogger.fine( - "Plaintext after DECRYPTION", bb.duplicate()); + "Plaintext after DECRYPTION", pt.duplicate()); } return new Plaintext(contentType, ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, - -1, -1L, bb.slice()); + -1, -1L, pt.slice()); } @Override diff --git a/test/jdk/sun/security/ssl/SSLCipher/ReadOnlyEngine.java b/test/jdk/sun/security/ssl/SSLCipher/ReadOnlyEngine.java new file mode 100644 index 00000000000..864a2589395 --- /dev/null +++ b/test/jdk/sun/security/ssl/SSLCipher/ReadOnlyEngine.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @library /javax/net/ssl/templates + * @bug 8283577 + * @summary Test SSLEngine to use read-only input bytebuffers + * @run main/othervm ReadOnlyEngine + */ + + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManagerFactory; +import java.io.FileInputStream; +import java.nio.ByteBuffer; +import java.security.KeyStore; +import java.security.Security; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ReadOnlyEngine { + + private final static String pathToStores = "../../../../javax/net/ssl/etc/"; + private final static String keyStoreFile = "keystore"; + private final static String trustStoreFile = "truststore"; + private final static char[] passwd = "passphrase".toCharArray(); + + private final static String keyFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + keyStoreFile; + private final static String trustFilename = + System.getProperty("test.src", "./") + "/" + pathToStores + + "/" + trustStoreFile; + + SSLEngine server; + SSLEngine client; + final static ExecutorService executor = Executors.newSingleThreadExecutor(); + + HandshakeStatus doHandshake(SSLEngine engine, ByteBuffer src, + ByteBuffer dst) { + HandshakeStatus status; + status = engine.getHandshakeStatus(); + while (status != SSLEngineResult.HandshakeStatus.FINISHED && + status != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { + dst.clear(); + switch (status) { + case NEED_UNWRAP: + try { + return receive(engine, src, dst); + } catch (SSLException e) { + e.printStackTrace(); + } + break; + case NEED_WRAP: + try { + return send(engine, src, dst); + } catch (SSLException e) { + e.printStackTrace(); + } + break; + case NEED_TASK: + Runnable task; + while ((task = engine.getDelegatedTask()) != null) { + executor.execute(task); + } + status = engine.getHandshakeStatus(); + break; + case FINISHED: + case NOT_HANDSHAKING: + break; + default: + throw new IllegalStateException("Invalid SSL status: " + + status); + } + } + return status; + } + + HandshakeStatus send(SSLEngine engine, ByteBuffer src, ByteBuffer dst) + throws SSLException { + SSLEngineResult status = engine.wrap(src, dst); + dst.flip(); + return status.getHandshakeStatus(); + } + + HandshakeStatus receive(SSLEngine engine, ByteBuffer src, ByteBuffer dst) + throws SSLException { + SSLEngineResult status = engine.unwrap(src, dst); + dst.flip(); + return status.getHandshakeStatus(); + } + + ReadOnlyEngine(SSLContext sslc, String ciphersuite) throws Exception { + System.err.println("==== Test Protocol: " + sslc.getProtocol() + + ", CipherSuite: " + ciphersuite); + KeyStore ks = KeyStore.getInstance("PKCS12"); + KeyStore ts = KeyStore.getInstance("PKCS12"); + + ks.load(new FileInputStream(keyFilename), passwd); + ts.load(new FileInputStream(trustFilename), passwd); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passwd); + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + client = sslc.createSSLEngine("client", 1); + client.setUseClientMode(true); + server = sslc.createSSLEngine("server", 2); + if (ciphersuite != null) { + server.setEnabledCipherSuites(new String[] { ciphersuite }); + } + server.setUseClientMode(false); + + SSLSession session = server.getSession(); + int maxData = session.getPacketBufferSize(); + + ByteBuffer in = ByteBuffer.allocate(maxData); + ByteBuffer out = ByteBuffer.allocate(maxData); + + HandshakeStatus statusClient, statusServer; + client.beginHandshake(); + server.beginHandshake(); + + // Do TLS handshake + do { + statusClient = doHandshake(client, out, in); + statusServer = doHandshake(server, in, out); + } while (statusClient != HandshakeStatus.NOT_HANDSHAKING || + statusServer != HandshakeStatus.NOT_HANDSHAKING); + + // Read New Session Ticket + in.clear(); + receive(client, out, in); + + System.out.println("done"); + + // Send bytes from the client and make sure the server receives the same + in.clear(); + out.clear(); + String testString = "ASDF"; + in.put(testString.getBytes()).flip(); + String testResult; + System.out.println("1: Client send: " + testString); + send(client, in.asReadOnlyBuffer(), out); + in.clear(); + receive(server, out.asReadOnlyBuffer(), in); + testResult = new String(in.array(), in.position(), in.limit() - in.position()); + + System.out.println("1: Server receive: " + testResult); + if (!testString.equalsIgnoreCase(testResult)) { + throw new Exception("unequal"); + } + + // Send bytes from the server and make sure the client receives the same + out.clear(); + in.clear(); + System.out.println("2: Server send: " + testString); + in.put(testString.getBytes()).flip(); + send(server, in.asReadOnlyBuffer(), out); + in.clear(); + receive(client, out.asReadOnlyBuffer() , in); + testResult = new String(in.array(), in.position(), in.limit() - in.position()); + System.out.println("2: Client receive: " + testResult); + if (!testString.equalsIgnoreCase(testResult)) { + throw new Exception("not equal"); + } + } + + public static void main(String[] args) throws Exception { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + new ReadOnlyEngine(SSLContext.getInstance("TLSv1.3"), + "TLS_AES_256_GCM_SHA384"); + new ReadOnlyEngine(SSLContext.getInstance("TLSv1.3"), + "TLS_CHACHA20_POLY1305_SHA256"); + new ReadOnlyEngine(SSLContext.getInstance("TLSv1.2"), + "TLS_RSA_WITH_AES_128_GCM_SHA256"); + new ReadOnlyEngine(SSLContext.getInstance("TLSv1.2"), + "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"); + new ReadOnlyEngine(SSLContext.getInstance("TLSv1.1"), + "TLS_RSA_WITH_AES_128_CBC_SHA"); + new ReadOnlyEngine(SSLContext.getInstance("TLSv1"), + "TLS_RSA_WITH_AES_128_CBC_SHA"); + } +}