8223482: Unsupported ciphersuites may be offered by a TLS client

Reviewed-by: xuelei, andrew
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 338c4ac..13917d2 100644
--- a/src/java.base/share/classes/sun/security/ssl/SSLCipher.java
+++ b/src/java.base/share/classes/sun/security/ssl/SSLCipher.java
@@ -31,6 +31,7 @@
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.Key;
+import java.security.NoSuchAlgorithmException;
 import java.security.PrivilegedAction;
 import java.security.SecureRandom;
 import java.security.Security;
@@ -465,16 +466,31 @@
 
         // availability of this bulk cipher
         //
-        // We assume all supported ciphers are always available since they are
-        // shipped with the SunJCE  provider.  However, AES/256 is unavailable
-        // when the default JCE policy jurisdiction files are installed because
-        // of key length restrictions.
-        this.isAvailable = allowed && isUnlimited(keySize, transformation);
+        // AES/256 is unavailable when the default JCE policy jurisdiction files
+        // are installed because of key length restrictions.
+        this.isAvailable = allowed && isUnlimited(keySize, transformation) &&
+                isTransformationAvailable(transformation);
 
         this.readCipherGenerators = readCipherGenerators;
         this.writeCipherGenerators = writeCipherGenerators;
     }
 
+    private static boolean isTransformationAvailable(String transformation) {
+        if (transformation.equals("NULL")) {
+            return true;
+        }
+        try {
+            JsseJce.getCipher(transformation);
+            return true;
+        } catch (NoSuchAlgorithmException e) {
+            if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+                SSLLogger.fine("Transformation " + transformation + " is" +
+                        " not available.");
+            }
+        }
+        return false;
+    }
+
     SSLReadCipher createReadCipher(Authenticator authenticator,
             ProtocolVersion protocolVersion,
             SecretKey key, IvParameterSpec iv,
diff --git a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java
index 6302fc1..7dd7bfa6 100644
--- a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java
+++ b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java
@@ -387,7 +387,8 @@
 
                 boolean isSupported = false;
                 for (ProtocolVersion protocol : protocols) {
-                    if (!suite.supports(protocol)) {
+                    if (!suite.supports(protocol) ||
+                            !suite.bulkCipher.isAvailable()) {
                         continue;
                     }
 
diff --git a/test/jdk/sun/security/pkcs11/fips/TestTLS12.java b/test/jdk/sun/security/pkcs11/fips/TestTLS12.java
index 73f9fb1..47655d8 100644
--- a/test/jdk/sun/security/pkcs11/fips/TestTLS12.java
+++ b/test/jdk/sun/security/pkcs11/fips/TestTLS12.java
@@ -376,15 +376,20 @@
 
         private static SSLEngine[][] getSSLEnginesToTest() throws Exception {
             SSLEngine[][] enginesToTest = new SSLEngine[2][2];
+            // TLS_RSA_WITH_AES_128_GCM_SHA256 ciphersuite is available but
+            // must not be chosen for the TLS connection if not supported.
+            // See JDK-8222937.
             String[][] preferredSuites = new String[][]{ new String[] {
+                    "TLS_RSA_WITH_AES_128_GCM_SHA256",
                     "TLS_RSA_WITH_AES_128_CBC_SHA256"
             },  new String[] {
+                    "TLS_RSA_WITH_AES_128_GCM_SHA256",
                     "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"
             }};
             for (int i = 0; i < enginesToTest.length; i++) {
                 enginesToTest[i][0] = createSSLEngine(true);
                 enginesToTest[i][1] = createSSLEngine(false);
-                enginesToTest[i][0].setEnabledCipherSuites(preferredSuites[i]);
+                // All CipherSuites enabled for the client.
                 enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]);
             }
             return enginesToTest;