changeset 7344:29cbb4617c92

Merge
author vinnie
date Tue, 16 Apr 2013 05:11:50 -0700
parents 6f80a6584fb9 (diff) 61cfbe08ce5d (current diff)
children 13e18d3ac414
files
diffstat 59 files changed, 3067 insertions(+), 1018 deletions(-) [+]
line wrap: on
line diff
--- a/make/sun/splashscreen/Makefile	Tue Apr 16 12:23:16 2013 +0100
+++ b/make/sun/splashscreen/Makefile	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2013, 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
@@ -83,21 +83,17 @@
 				  -framework JavaNativeFoundation
 else ifneq ($(PLATFORM), windows)
   CFLAGS += -DWITH_X11
-  ifeq ($(PLATFORM), macosx))
-    OTHER_LDLIBS += -liconv
-    CPPFLAGS += -I$(OPENWIN_HOME)/include \
-                -I$(OPENWIN_HOME)/include/X11/extensions
-    OTHER_LDLIBS += -L$(OPENWIN_LIB) -lX11 -lXext $(LIBM) -pthread
-  else
-    CPPFLAGS += -I$(OPENWIN_HOME)/include -I$(OPENWIN_HOME)/include/X11/extensions
-    OTHER_LDLIBS += -L$(OPENWIN_LIB) -lX11 -lXext $(LIBM) -lpthread
-  endif
+  CPPFLAGS += -I$(OPENWIN_HOME)/include -I$(OPENWIN_HOME)/include/X11/extensions
+  OTHER_LDLIBS += -L$(OPENWIN_LIB) -lX11 -lXext $(LIBM) -lpthread
 else # PLATFORM
   CFLAGS += -DWITH_WIN32
   OTHER_LDLIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib /DELAYLOAD:user32.dll
 #$(JVMLIB) $(OBJDIR)/../../jpeg/$(OBJDIRNAME)/jpeg$(SUFFIX).lib
 endif # PLATFORM
 
+# Add giflib include path for all platforms
+CPPFLAGS += -I$(SHARE_SRC)/native/sun/awt/giflib
+
 #
 # Add to ambient vpath to get files in a subdirectory
 #
--- a/src/share/classes/com/sun/crypto/provider/CipherCore.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java	Tue Apr 16 05:11:50 2013 -0700
@@ -426,17 +426,13 @@
            }
         }
         try {
-            params = AlgorithmParameters.getInstance(algName, "SunJCE");
+            params = AlgorithmParameters.getInstance(algName,
+                    SunJCE.getInstance());
+            params.init(spec);
         } catch (NoSuchAlgorithmException nsae) {
             // should never happen
             throw new RuntimeException("Cannot find " + algName +
                 " AlgorithmParameters implementation in SunJCE provider");
-        } catch (NoSuchProviderException nspe) {
-            // should never happen
-            throw new RuntimeException("Cannot find SunJCE provider");
-        }
-        try {
-            params.init(spec);
         } catch (InvalidParameterSpecException ipse) {
             // should never happen
             throw new RuntimeException(spec.getClass() + " not supported");
--- a/src/share/classes/com/sun/crypto/provider/CipherWithWrappingSpi.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/CipherWithWrappingSpi.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, 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
@@ -169,7 +169,8 @@
 
         try {
             KeyFactory keyFactory =
-                KeyFactory.getInstance(encodedKeyAlgorithm, "SunJCE");
+                KeyFactory.getInstance(encodedKeyAlgorithm,
+                    SunJCE.getInstance());
             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
             key = keyFactory.generatePublic(keySpec);
         } catch (NoSuchAlgorithmException nsae) {
@@ -191,8 +192,6 @@
             }
         } catch (InvalidKeySpecException ikse) {
             // Should never happen.
-        } catch (NoSuchProviderException nspe) {
-            // Should never happen.
         }
 
         return key;
@@ -215,7 +214,8 @@
 
         try {
             KeyFactory keyFactory =
-                KeyFactory.getInstance(encodedKeyAlgorithm, "SunJCE");
+                KeyFactory.getInstance(encodedKeyAlgorithm,
+                    SunJCE.getInstance());
             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
             return keyFactory.generatePrivate(keySpec);
         } catch (NoSuchAlgorithmException nsae) {
@@ -237,8 +237,6 @@
             }
         } catch (InvalidKeySpecException ikse) {
             // Should never happen.
-        } catch (NoSuchProviderException nspe) {
-            // Should never happen.
         }
 
         return key;
--- a/src/share/classes/com/sun/crypto/provider/ConstructKeys.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/ConstructKeys.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2013, 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
@@ -30,7 +30,6 @@
 import java.security.PrivateKey;
 import java.security.KeyFactory;
 import java.security.InvalidKeyException;
-import java.security.NoSuchProviderException;
 import java.security.NoSuchAlgorithmException;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
@@ -66,7 +65,8 @@
 
         try {
             KeyFactory keyFactory =
-                KeyFactory.getInstance(encodedKeyAlgorithm, "SunJCE");
+                KeyFactory.getInstance(encodedKeyAlgorithm,
+                    SunJCE.getInstance());
             X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
             key = keyFactory.generatePublic(keySpec);
         } catch (NoSuchAlgorithmException nsae) {
@@ -94,8 +94,6 @@
                 new InvalidKeyException("Cannot construct public key");
             ike.initCause(ikse);
             throw ike;
-        } catch (NoSuchProviderException nspe) {
-            // Should never happen.
         }
 
         return key;
@@ -118,7 +116,8 @@
 
         try {
             KeyFactory keyFactory =
-                KeyFactory.getInstance(encodedKeyAlgorithm, "SunJCE");
+                KeyFactory.getInstance(encodedKeyAlgorithm,
+                    SunJCE.getInstance());
             PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
             return keyFactory.generatePrivate(keySpec);
         } catch (NoSuchAlgorithmException nsae) {
@@ -146,8 +145,6 @@
                 new InvalidKeyException("Cannot construct private key");
             ike.initCause(ikse);
             throw ike;
-        } catch (NoSuchProviderException nspe) {
-            // Should never happen.
         }
 
         return key;
--- a/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Tue Apr 16 05:11:50 2013 -0700
@@ -389,17 +389,13 @@
         if (iv != null) {
             String algo = cipherKey.getAlgorithm();
             try {
-                params = AlgorithmParameters.getInstance(algo, "SunJCE");
+                params = AlgorithmParameters.getInstance(algo,
+                    SunJCE.getInstance());
+                params.init(new IvParameterSpec(iv));
             } catch (NoSuchAlgorithmException nsae) {
                 // should never happen
                 throw new RuntimeException("Cannot find " + algo +
                     " AlgorithmParameters implementation in SunJCE provider");
-            } catch (NoSuchProviderException nspe) {
-                // should never happen
-                throw new RuntimeException("Cannot find SunJCE provider");
-            }
-            try {
-                params.init(new IvParameterSpec(iv));
             } catch (InvalidParameterSpecException ipse) {
                 // should never happen
                 throw new RuntimeException("IvParameterSpec not supported");
--- a/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/DHParameterGenerator.java	Tue Apr 16 05:11:50 2013 -0700
@@ -151,7 +151,8 @@
                 dhParamSpec = new DHParameterSpec(dsaParamSpec.getP(),
                                                   dsaParamSpec.getG());
             }
-            algParams = AlgorithmParameters.getInstance("DH", "SunJCE");
+            algParams = AlgorithmParameters.getInstance("DH",
+                    SunJCE.getInstance());
             algParams.init(dhParamSpec);
         } catch (InvalidParameterSpecException e) {
             // this should never happen
@@ -159,11 +160,7 @@
         } catch (NoSuchAlgorithmException e) {
             // this should never happen, because we provide it
             throw new RuntimeException(e.getMessage());
-        } catch (NoSuchProviderException e) {
-            // this should never happen, because we provide it
-            throw new RuntimeException(e.getMessage());
         }
-
         return algParams;
     }
 }
--- a/src/share/classes/com/sun/crypto/provider/KeyProtector.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/KeyProtector.java	Tue Apr 16 05:11:50 2013 -0700
@@ -81,8 +81,6 @@
     // key protector
     private char[] password;
 
-    private static final Provider PROV = Security.getProvider("SunJCE");
-
     KeyProtector(char[] password) {
         if (password == null) {
            throw new IllegalArgumentException("password can't be null");
@@ -119,7 +117,7 @@
         // wrap encrypted private key in EncryptedPrivateKeyInfo
         // (as defined in PKCS#8)
         AlgorithmParameters pbeParams =
-            AlgorithmParameters.getInstance("PBE", PROV);
+            AlgorithmParameters.getInstance("PBE", SunJCE.getInstance());
         pbeParams.init(pbeSpec);
 
         AlgorithmId encrAlg = new AlgorithmId
@@ -299,7 +297,7 @@
 
         PBEWithMD5AndTripleDESCipher cipherSpi;
         cipherSpi = new PBEWithMD5AndTripleDESCipher();
-        cipher = new CipherForKeyProtector(cipherSpi, PROV,
+        cipher = new CipherForKeyProtector(cipherSpi, SunJCE.getInstance(),
                                            "PBEWithMD5AndTripleDES");
         cipher.init(Cipher.ENCRYPT_MODE, sKey, pbeSpec);
         return new SealedObjectForKeyProtector(key, cipher);
@@ -330,8 +328,9 @@
             }
             PBEWithMD5AndTripleDESCipher cipherSpi;
             cipherSpi = new PBEWithMD5AndTripleDESCipher();
-            Cipher cipher = new CipherForKeyProtector(cipherSpi, PROV,
-                                                   "PBEWithMD5AndTripleDES");
+            Cipher cipher = new CipherForKeyProtector(cipherSpi,
+                                                      SunJCE.getInstance(),
+                                                      "PBEWithMD5AndTripleDES");
             cipher.init(Cipher.DECRYPT_MODE, skey, params);
             return (Key)soForKeyProtector.getObject(cipher);
         } catch (NoSuchAlgorithmException ex) {
--- a/src/share/classes/com/sun/crypto/provider/PBECipherCore.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBECipherCore.java	Tue Apr 16 05:11:50 2013 -0700
@@ -169,16 +169,12 @@
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
         try {
             params = AlgorithmParameters.getInstance("PBEWithMD5And" +
-                (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"), "SunJCE");
+                (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"),
+                    SunJCE.getInstance());
+            params.init(pbeSpec);
         } catch (NoSuchAlgorithmException nsae) {
             // should never happen
             throw new RuntimeException("SunJCE called, but not configured");
-        } catch (NoSuchProviderException nspe) {
-            // should never happen
-            throw new RuntimeException("SunJCE called, but not configured");
-        }
-        try {
-            params.init(pbeSpec);
         } catch (InvalidParameterSpecException ipse) {
             // should never happen
             throw new RuntimeException("PBEParameterSpec not supported");
--- a/src/share/classes/com/sun/crypto/provider/PBES1Core.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBES1Core.java	Tue Apr 16 05:11:50 2013 -0700
@@ -169,16 +169,12 @@
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
         try {
             params = AlgorithmParameters.getInstance("PBEWithMD5And" +
-                (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"), "SunJCE");
+                (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"),
+                SunJCE.getInstance());
+            params.init(pbeSpec);
         } catch (NoSuchAlgorithmException nsae) {
             // should never happen
             throw new RuntimeException("SunJCE called, but not configured");
-        } catch (NoSuchProviderException nspe) {
-            // should never happen
-            throw new RuntimeException("SunJCE called, but not configured");
-        }
-        try {
-            params.init(pbeSpec);
         } catch (InvalidParameterSpecException ipse) {
             // should never happen
             throw new RuntimeException("PBEParameterSpec not supported");
--- a/src/share/classes/com/sun/crypto/provider/PBES2Core.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBES2Core.java	Tue Apr 16 05:11:50 2013 -0700
@@ -25,11 +25,9 @@
 
 package com.sun.crypto.provider;
 
-import java.io.UnsupportedEncodingException;
 import java.security.*;
 import java.security.spec.*;
 import javax.crypto.*;
-import javax.crypto.interfaces.*;
 import javax.crypto.spec.*;
 
 /**
@@ -145,16 +143,12 @@
         }
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount, ivSpec);
         try {
-            params = AlgorithmParameters.getInstance(pbeAlgo, "SunJCE");
+            params = AlgorithmParameters.getInstance(pbeAlgo,
+                SunJCE.getInstance());
+            params.init(pbeSpec);
         } catch (NoSuchAlgorithmException nsae) {
             // should never happen
             throw new RuntimeException("SunJCE called, but not configured");
-        } catch (NoSuchProviderException nspe) {
-            // should never happen
-            throw new RuntimeException("SunJCE called, but not configured");
-        }
-        try {
-            params.init(pbeSpec);
         } catch (InvalidParameterSpecException ipse) {
             // should never happen
             throw new RuntimeException("PBEParameterSpec not supported");
--- a/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -33,7 +33,6 @@
 import java.security.KeyRep;
 import java.security.GeneralSecurityException;
 import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
 import java.security.spec.InvalidKeySpecException;
 import javax.crypto.Mac;
 import javax.crypto.SecretKey;
@@ -102,21 +101,16 @@
         int keyLength = keySpec.getKeyLength();
         if (keyLength == 0) {
             throw new InvalidKeySpecException("Key length not found");
-        } else if (keyLength == 0) {
+        } else if (keyLength < 0) {
             throw new InvalidKeySpecException("Key length is negative");
         }
         try {
-            this.prf = Mac.getInstance(prfAlgo, "SunJCE");
+            this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
         } catch (NoSuchAlgorithmException nsae) {
             // not gonna happen; re-throw just in case
             InvalidKeySpecException ike = new InvalidKeySpecException();
             ike.initCause(nsae);
             throw ike;
-        } catch (NoSuchProviderException nspe) {
-            // Again, not gonna happen; re-throw just in case
-            InvalidKeySpecException ike = new InvalidKeySpecException();
-            ike.initCause(nspe);
-            throw ike;
         }
         this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
     }
--- a/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java	Tue Apr 16 05:11:50 2013 -0700
@@ -25,7 +25,6 @@
 
 package com.sun.crypto.provider;
 
-import java.io.UnsupportedEncodingException;
 import java.math.BigInteger;
 import java.security.*;
 import java.security.spec.*;
@@ -232,14 +231,13 @@
         }
         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
         try {
-            params = AlgorithmParameters.getInstance(pbeAlgo, "SunJCE");
-        } catch (GeneralSecurityException gse) {
+            params = AlgorithmParameters.getInstance(pbeAlgo,
+                SunJCE.getInstance());
+            params.init(pbeSpec);
+        } catch (NoSuchAlgorithmException nsae) {
             // should never happen
             throw new RuntimeException(
                 "SunJCE provider is not configured properly");
-        }
-        try {
-            params.init(pbeSpec);
         } catch (InvalidParameterSpecException ipse) {
             // should never happen
             throw new RuntimeException("PBEParameterSpec not supported");
--- a/src/share/classes/com/sun/crypto/provider/RSACipher.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/RSACipher.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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
@@ -178,16 +178,14 @@
         if (spec != null) {
             try {
                 AlgorithmParameters params =
-                    AlgorithmParameters.getInstance("OAEP", "SunJCE");
+                    AlgorithmParameters.getInstance("OAEP",
+                        SunJCE.getInstance());
                 params.init(spec);
                 return params;
             } catch (NoSuchAlgorithmException nsae) {
                 // should never happen
                 throw new RuntimeException("Cannot find OAEP " +
                     " AlgorithmParameters implementation in SunJCE provider");
-            } catch (NoSuchProviderException nspe) {
-                // should never happen
-                throw new RuntimeException("Cannot find SunJCE provider");
             } catch (InvalidParameterSpecException ipse) {
                 // should never happen
                 throw new RuntimeException("OAEPParameterSpec not supported");
--- a/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/SealedObjectForKeyProtector.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, 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
@@ -46,14 +46,15 @@
         AlgorithmParameters params = null;
         if (super.encodedParams != null) {
             try {
-                params = AlgorithmParameters.getInstance("PBE", "SunJCE");
+                params = AlgorithmParameters.getInstance("PBE",
+                    SunJCE.getInstance());
                 params.init(super.encodedParams);
-            } catch (NoSuchProviderException nspe) {
-                // eat.
             } catch (NoSuchAlgorithmException nsae) {
-                //eat.
-            } catch (IOException ioe) {
-                //eat.
+                throw new RuntimeException(
+                    "SunJCE provider is not configured properly");
+            } catch (IOException io) {
+                throw new RuntimeException("Parameter failure: "+
+                    io.getMessage());
             }
         }
         return params;
--- a/src/share/classes/com/sun/crypto/provider/SunJCE.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/SunJCE.java	Tue Apr 16 05:11:50 2013 -0700
@@ -91,6 +91,10 @@
     /* Are we debugging? -- for developers */
     static final boolean debug = false;
 
+    // Instance of this provider, so we don't have to call the provider list
+    // to find ourselves or run the risk of not being in the list.
+    private static volatile SunJCE instance = null;
+
     // lazy initialize SecureRandom to avoid potential recursion if Sun
     // provider has not been installed yet
     private static class SecureRandomHolder {
@@ -770,5 +774,17 @@
                     return null;
                 }
             });
+
+        if (instance == null) {
+            instance = this;
+        }
+    }
+
+    // Return the instance of this class or create one if needed.
+    static SunJCE getInstance() {
+        if (instance == null) {
+            return new SunJCE();
+        }
+        return instance;
     }
 }
--- a/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/com/sun/crypto/provider/TlsKeyMaterialGenerator.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -165,16 +165,18 @@
         // partition keyblock into individual secrets
 
         int ofs = 0;
-        byte[] tmp = new byte[macLength];
+        if (macLength != 0) {
+            byte[] tmp = new byte[macLength];
 
-        // mac keys
-        System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
-        ofs += macLength;
-        clientMacKey = new SecretKeySpec(tmp, "Mac");
+            // mac keys
+            System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
+            ofs += macLength;
+            clientMacKey = new SecretKeySpec(tmp, "Mac");
 
-        System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
-        ofs += macLength;
-        serverMacKey = new SecretKeySpec(tmp, "Mac");
+            System.arraycopy(keyBlock, ofs, tmp, 0, macLength);
+            ofs += macLength;
+            serverMacKey = new SecretKeySpec(tmp, "Mac");
+        }
 
         if (keyLength == 0) { // SSL_RSA_WITH_NULL_* ciphersuites
             return new TlsKeyMaterialSpec(clientMacKey, serverMacKey);
@@ -198,7 +200,7 @@
 
             // IV keys if needed.
             if (ivLength != 0) {
-                tmp = new byte[ivLength];
+                byte[] tmp = new byte[ivLength];
 
                 System.arraycopy(keyBlock, ofs, tmp, 0, ivLength);
                 ofs += ivLength;
@@ -220,8 +222,8 @@
                 // TLS 1.0
                 byte[] seed = concat(clientRandom, serverRandom);
 
-                tmp = doTLS10PRF(clientKeyBytes, LABEL_CLIENT_WRITE_KEY, seed,
-                            expandedKeyLength, md5, sha);
+                byte[] tmp = doTLS10PRF(clientKeyBytes,
+                    LABEL_CLIENT_WRITE_KEY, seed, expandedKeyLength, md5, sha);
                 clientCipherKey = new SecretKeySpec(tmp, alg);
 
                 tmp = doTLS10PRF(serverKeyBytes, LABEL_SERVER_WRITE_KEY, seed,
@@ -239,7 +241,7 @@
                 }
             } else {
                 // SSLv3
-                tmp = new byte[expandedKeyLength];
+                byte[] tmp = new byte[expandedKeyLength];
 
                 md5.update(clientKeyBytes);
                 md5.update(clientRandom);
--- a/src/share/classes/java/security/SecureRandom.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/java/security/SecureRandom.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, 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
@@ -26,6 +26,7 @@
 package java.security;
 
 import java.util.*;
+import java.util.regex.*;
 
 import java.security.Provider.Service;
 
@@ -79,7 +80,7 @@
  *
  * Note: Depending on the implementation, the <code>generateSeed</code> and
  * <code>nextBytes</code> methods may block as entropy is being gathered,
- * for example, if they need to read from /dev/random on various unix-like
+ * for example, if they need to read from /dev/random on various Unix-like
  * operating systems.
  *
  * @see java.security.SecureRandomSpi
@@ -428,6 +429,7 @@
      *
      * @see #getSeed
      */
+    @Override
     public void setSeed(long seed) {
         /*
          * Ignore call from super constructor (as well as any other calls
@@ -450,7 +452,7 @@
      *
      * @param bytes the array to be filled in with random bytes.
      */
-
+    @Override
     synchronized public void nextBytes(byte[] bytes) {
         secureRandomSpi.engineNextBytes(bytes);
     }
@@ -469,14 +471,16 @@
      * @return an <code>int</code> containing the user-specified number
      * of pseudo-random bits (right justified, with leading zeros).
      */
+    @Override
     final protected int next(int numBits) {
         int numBytes = (numBits+7)/8;
         byte b[] = new byte[numBytes];
         int next = 0;
 
         nextBytes(b);
-        for (int i = 0; i < numBytes; i++)
+        for (int i = 0; i < numBytes; i++) {
             next = (next << 8) + (b[i] & 0xFF);
+        }
 
         return next >>> (numBytes*8 - numBits);
     }
@@ -499,8 +503,9 @@
      * @see #setSeed
      */
     public static byte[] getSeed(int numBytes) {
-        if (seedGenerator == null)
+        if (seedGenerator == null) {
             seedGenerator = new SecureRandom();
+        }
         return seedGenerator.generateSeed(numBytes);
     }
 
@@ -549,6 +554,104 @@
         return null;
     }
 
+    /*
+     * Lazily initialize since Pattern.compile() is heavy.
+     * Effective Java (2nd Edition), Item 71.
+     */
+    private static final class StrongPatternHolder {
+        /*
+         * Entries are alg:prov separated by ,
+         * Allow for prepended/appended whitespace between entries.
+         *
+         * Capture groups:
+         *     1 - alg
+         *     2 - :prov (optional)
+         *     3 - prov (optional)
+         *     4 - ,nextEntry (optional)
+         *     5 - nextEntry (optional)
+         */
+        private static Pattern pattern =
+            Pattern.compile(
+                "\\s*([\\S&&[^:,]]*)(\\:([\\S&&[^,]]*))?\\s*(\\,(.*))?");
+    }
+
+    /**
+     * Returns a {@code SecureRandom} object that was selected by using
+     * the algorithms/providers specified in the {@code
+     * securerandom.strongAlgorithms} Security property.
+     * <p>
+     * Some situations require strong random values, such as when
+     * creating high-value/long-lived secrets like RSA public/private
+     * keys.  To help guide applications in selecting a suitable strong
+     * {@code SecureRandom} implementation, Java distributions should
+     * include a list of known strong {@code SecureRandom}
+     * implementations in the {@code securerandom.strongAlgorithms}
+     * Security property.
+     *
+     * <pre>
+     *     SecureRandom sr = SecureRandom.getStrongSecureRandom();
+     *
+     *     if (sr == null) {
+     *         // Decide if this is a problem, and whether to recover.
+     *         sr = new SecureRandom();
+     *         if (!goodEnough(sr)) {
+     *             return;
+     *         }
+     *     }
+     *
+     *     keyPairGenerator.initialize(2048, sr);
+     * </pre>
+     *
+     * @return a strong {@code SecureRandom} implementation as indicated
+     * by the {@code securerandom.strongAlgorithms} Security property, or
+     * null if none are available.
+     *
+     * @see Security#getProperty(String)
+     *
+     * @since 1.8
+     */
+    public static SecureRandom getStrongSecureRandom() {
+
+        String property = AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                @Override
+                public String run() {
+                    return Security.getProperty(
+                        "securerandom.strongAlgorithms");
+                }
+            });
+
+        if ((property == null) || (property.length() == 0)) {
+            return null;
+        }
+
+        String remainder = property;
+        while (remainder != null) {
+            Matcher m;
+            if ((m = StrongPatternHolder.pattern.matcher(
+                    remainder)).matches()) {
+
+                String alg = m.group(1);
+                String prov = m.group(3);
+
+                try {
+                    if (prov == null) {
+                        return SecureRandom.getInstance(alg);
+                    } else {
+                        return SecureRandom.getInstance(alg, prov);
+                    }
+                } catch (NoSuchAlgorithmException |
+                        NoSuchProviderException e) {
+                }
+                remainder = m.group(5);
+            } else {
+                remainder = null;
+            }
+        }
+
+        return null;
+    }
+
     // Declare serialVersionUID to be compatible with JDK1.1
     static final long serialVersionUID = 4940670005562187L;
 
--- a/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/internal/spec/TlsKeyMaterialParameterSpec.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -212,12 +212,6 @@
      *     generated.
      */
     public int getIvLength() {
-        // TLS v1.1 or later uses an explicit IV to protect against
-        // the CBC attacks.
-        if (majorVersion >= 0x03 && minorVersion >= 0x02) {
-            return 0;
-        }
-
         return ivLength;
     }
 
--- a/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/internal/spec/TlsKeyMaterialSpec.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -58,9 +58,8 @@
      * <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey,
      * null, null, null, null)</code>.
      *
-     * @param clientMacKey the client MAC key
-     * @param serverMacKey the server MAC key
-     * @throws NullPointerException if clientMacKey or serverMacKey is null
+     * @param clientMacKey the client MAC key (or null)
+     * @param serverMacKey the server MAC key (or null)
      */
     public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey) {
         this(clientMacKey, serverMacKey, null, null, null, null);
@@ -73,11 +72,10 @@
      * <code>new TlsKeymaterialSpec(clientMacKey, serverMacKey,
      * clientCipherKey, serverCipherKey, null, null)</code>.
      *
-     * @param clientMacKey the client MAC key
-     * @param serverMacKey the server MAC key
+     * @param clientMacKey the client MAC key (or null)
+     * @param serverMacKey the server MAC key (or null)
      * @param clientCipherKey the client cipher key (or null)
      * @param serverCipherKey the server cipher key (or null)
-     * @throws NullPointerException if clientMacKey or serverMacKey is null
      */
     public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
             SecretKey clientCipherKey, SecretKey serverCipherKey) {
@@ -90,21 +88,17 @@
      * keys, client and server cipher keys, and client and server
      * initialization vectors.
      *
-     * @param clientMacKey the client MAC key
-     * @param serverMacKey the server MAC key
+     * @param clientMacKey the client MAC key (or null)
+     * @param serverMacKey the server MAC key (or null)
      * @param clientCipherKey the client cipher key (or null)
      * @param clientIv the client initialization vector (or null)
      * @param serverCipherKey the server cipher key (or null)
      * @param serverIv the server initialization vector (or null)
-     *
-     * @throws NullPointerException if clientMacKey or serverMacKey is null
      */
     public TlsKeyMaterialSpec(SecretKey clientMacKey, SecretKey serverMacKey,
             SecretKey clientCipherKey, IvParameterSpec clientIv,
             SecretKey serverCipherKey, IvParameterSpec serverIv) {
-        if ((clientMacKey == null) || (serverMacKey == null)) {
-            throw new NullPointerException("MAC keys must not be null");
-        }
+
         this.clientMacKey = clientMacKey;
         this.serverMacKey = serverMacKey;
         this.clientCipherKey = clientCipherKey;
@@ -143,7 +137,7 @@
     /**
      * Returns the client MAC key.
      *
-     * @return the client MAC key.
+     * @return the client MAC key (or null).
      */
     public SecretKey getClientMacKey() {
         return clientMacKey;
@@ -152,7 +146,7 @@
     /**
      * Return the server MAC key.
      *
-     * @return the server MAC key.
+     * @return the server MAC key (or null).
      */
     public SecretKey getServerMacKey() {
         return serverMacKey;
--- a/src/share/classes/sun/security/pkcs11/P11SecureRandom.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/pkcs11/P11SecureRandom.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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,12 +25,9 @@
 
 package sun.security.pkcs11;
 
-import java.util.*;
 import java.io.*;
 import java.security.*;
-
 import sun.security.pkcs11.wrapper.*;
-import sun.security.pkcs11.wrapper.PKCS11Constants.*;
 
 /**
  * SecureRandom implementation class. Some tokens support only
@@ -88,6 +85,7 @@
     }
 
     // see JCA spec
+    @Override
     protected synchronized void engineSetSeed(byte[] seed) {
         if (seed == null) {
             throw new NullPointerException("seed must not be null");
@@ -119,6 +117,7 @@
     }
 
     // see JCA spec
+    @Override
     protected void engineNextBytes(byte[] bytes) {
         if ((bytes == null) || (bytes.length == 0)) {
             return;
@@ -149,6 +148,7 @@
     }
 
     // see JCA spec
+    @Override
     protected byte[] engineGenerateSeed(int numBytes) {
         byte[] b = new byte[numBytes];
         engineNextBytes(b);
--- a/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -168,10 +168,22 @@
             // Note that the MAC keys do not inherit all attributes from the
             // template, but they do inherit the sensitive/extractable/token
             // flags, which is all P11Key cares about.
-            SecretKey clientMacKey = P11Key.secretKey
+            SecretKey clientMacKey, serverMacKey;
+
+            // The MAC size may be zero for GCM mode.
+            //
+            // PKCS11 does not support GCM mode as the author made the comment,
+            // so the macBits is unlikely to be zero. It's only a place holder.
+            if (macBits != 0) {
+                clientMacKey = P11Key.secretKey
                     (session, out.hClientMacSecret, "MAC", macBits, attributes);
-            SecretKey serverMacKey = P11Key.secretKey
+                serverMacKey = P11Key.secretKey
                     (session, out.hServerMacSecret, "MAC", macBits, attributes);
+            } else {
+                clientMacKey = null;
+                serverMacKey = null;
+            }
+
             SecretKey clientCipherKey, serverCipherKey;
             if (keyBits != 0) {
                 clientCipherKey = P11Key.secretKey(session, out.hClientKey,
--- a/src/share/classes/sun/security/provider/SecureRandom.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/provider/SecureRandom.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, 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
@@ -79,7 +79,7 @@
     }
 
     /**
-     * This constructor is used to instatiate the private seeder object
+     * This constructor is used to instantiate the private seeder object
      * with a given seed from the SeedGenerator.
      *
      * @param seed the seed.
@@ -94,7 +94,7 @@
      */
     private void init(byte[] seed) {
         try {
-            digest = MessageDigest.getInstance ("SHA");
+            digest = MessageDigest.getInstance("SHA");
         } catch (NoSuchAlgorithmException e) {
             throw new InternalError("internal error: SHA-1 not available.", e);
         }
@@ -120,7 +120,10 @@
      *
      * @return the seed bytes.
      */
+    @Override
     public byte[] engineGenerateSeed(int numBytes) {
+        // Neither of the SeedGenerator implementations require
+        // locking, so no sync needed here.
         byte[] b = new byte[numBytes];
         SeedGenerator.generateSeed(b);
         return b;
@@ -133,19 +136,21 @@
      *
      * @param seed the seed.
      */
+    @Override
     synchronized public void engineSetSeed(byte[] seed) {
         if (state != null) {
             digest.update(state);
-            for (int i = 0; i < state.length; i++)
+            for (int i = 0; i < state.length; i++) {
                 state[i] = 0;
+            }
         }
         state = digest.digest(seed);
     }
 
     private static void updateState(byte[] state, byte[] output) {
         int last = 1;
-        int v = 0;
-        byte t = 0;
+        int v;
+        byte t;
         boolean zf = false;
 
         // state(n + 1) = (state(n) + output(n) + 1) % 2^160;
@@ -162,8 +167,9 @@
         }
 
         // Make sure at least one bit changes!
-        if (!zf)
+        if (!zf) {
            state[0]++;
+        }
     }
 
     /**
@@ -193,6 +199,7 @@
      *
      * @param bytes the array to be filled in with random bytes.
      */
+    @Override
     public synchronized void engineNextBytes(byte[] result) {
         int index = 0;
         int todo;
@@ -258,7 +265,7 @@
         s.defaultReadObject ();
 
         try {
-            digest = MessageDigest.getInstance ("SHA");
+            digest = MessageDigest.getInstance("SHA");
         } catch (NoSuchAlgorithmException e) {
             throw new InternalError("internal error: SHA-1 not available.", e);
         }
--- a/src/share/classes/sun/security/provider/SeedGenerator.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/provider/SeedGenerator.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, 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
@@ -26,11 +26,13 @@
 package sun.security.provider;
 
 /**
- * <P> This class generates seeds for the cryptographically strong random
- * number generator.
- * <P> The seed is produced using one of two techniques, via a computation
+ * This class generates seeds for the SHA1PRNG cryptographically strong
+ * random number generator.
+ * <p>
+ * The seed is produced using one of two techniques, via a computation
  * of current system activity or from an entropy gathering device.
- * <p> In the default technique the seed is  produced by counting the
+ * <p>
+ * In the default technique the seed is produced by counting the
  * number of times the VM manages to loop in a given period. This number
  * roughly reflects the machine load at that point in time.
  * The samples are translated using a permutation (s-box)
@@ -41,23 +43,24 @@
  * We also create a number of sleeper threads which add entropy
  * to the system by keeping the scheduler busy.
  * Twenty such samples should give us roughly 160 bits of randomness.
- * <P> These values are gathered in the background by a daemon thread
+ * <p>
+ * These values are gathered in the background by a daemon thread
  * thus allowing the system to continue performing it's different
  * activites, which in turn add entropy to the random seed.
- * <p> The class also gathers miscellaneous system information, some
+ * <p>
+ * The class also gathers miscellaneous system information, some
  * machine dependent, some not. This information is then hashed together
  * with the 20 seed bytes.
- * <P> The alternative to the above approach is to acquire seed material
+ * <p>
+ * The alternative to the above approach is to acquire seed material
  * from an entropy gathering device, such as /dev/random. This can be
- * accomplished by setting the value of the "securerandom.source"
- * security property (in the Java security properties file) to a URL
- * specifying the location of the entropy gathering device.
+ * accomplished by setting the value of the {@code securerandom.source}
+ * Security property to a URL specifying the location of the entropy
+ * gathering device, or by setting the {@code java.security.egd} System
+ * property.
+ * <p>
  * In the event the specified URL cannot be accessed the default
- * mechanism is used.
- * The Java security properties file is located in the file named
- * &lt;JAVA_HOME&gt;/lib/security/java.security.
- * &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
- * and specifies the directory where the JRE is installed.
+ * threading mechanism is used.
  *
  * @author Joshua Bloch
  * @author Gadi Guy
@@ -81,27 +84,28 @@
 
     private static final Debug debug = Debug.getInstance("provider");
 
-    final static String URL_DEV_RANDOM = SunEntries.URL_DEV_RANDOM;
-    final static String URL_DEV_URANDOM = SunEntries.URL_DEV_URANDOM;
-
     // Static initializer to hook in selected or best performing generator
     static {
         String egdSource = SunEntries.getSeedSource();
 
-        // Try the URL specifying the source
-        // e.g. file:/dev/random
-        //
-        // The URL file:/dev/random or file:/dev/urandom is used to indicate
-        // the SeedGenerator using OS support, if available.
-        // On Windows, the causes MS CryptoAPI to be used.
-        // On Solaris and Linux, this is the identical to using
-        // URLSeedGenerator to read from /dev/random
-
-        if (egdSource.equals(URL_DEV_RANDOM) || egdSource.equals(URL_DEV_URANDOM)) {
+        /*
+         * Try the URL specifying the source (e.g. file:/dev/random)
+         *
+         * The URLs "file:/dev/random" or "file:/dev/urandom" are used to
+         * indicate the SeedGenerator should use OS support, if available.
+         *
+         * On Windows, this causes the MS CryptoAPI seeder to be used.
+         *
+         * On Solaris/Linux/MacOS, this is identical to using
+         * URLSeedGenerator to read from /dev/[u]random
+         */
+        if (egdSource.equals(SunEntries.URL_DEV_RANDOM) ||
+                egdSource.equals(SunEntries.URL_DEV_URANDOM)) {
             try {
-                instance = new NativeSeedGenerator();
+                instance = new NativeSeedGenerator(egdSource);
                 if (debug != null) {
-                    debug.println("Using operating system seed generator");
+                    debug.println(
+                        "Using operating system seed generator" + egdSource);
                 }
             } catch (IOException e) {
                 if (debug != null) {
@@ -117,9 +121,10 @@
                                   + egdSource);
                 }
             } catch (IOException e) {
-                if (debug != null)
+                if (debug != null) {
                     debug.println("Failed to create seed generator with "
                                   + egdSource + ": " + e.toString());
+                }
             }
         }
 
@@ -161,8 +166,8 @@
 
         java.security.AccessController.doPrivileged
             (new java.security.PrivilegedAction<Void>() {
+                @Override
                 public Void run() {
-
                     try {
                         // System properties can change from machine to machine
                         String s;
@@ -180,7 +185,9 @@
                         // The temporary dir
                         File f = new File(p.getProperty("java.io.tmpdir"));
                         int count = 0;
-                        try (DirectoryStream<Path> stream = Files.newDirectoryStream(f.toPath())) {
+                        try (
+                            DirectoryStream<Path> stream =
+                                Files.newDirectoryStream(f.toPath())) {
                             // We use a Random object to choose what file names
                             // should be used. Otherwise on a machine with too
                             // many files, the same first 1024 files always get
@@ -189,7 +196,8 @@
                             Random r = new Random();
                             for (Path entry: stream) {
                                 if (count < 512 || r.nextBoolean()) {
-                                    md.update(entry.getFileName().toString().getBytes());
+                                    md.update(entry.getFileName()
+                                        .toString().getBytes());
                                 }
                                 if (count++ > 1024) {
                                     break;
@@ -236,7 +244,8 @@
     */
 
 
-    private static class ThreadedSeedGenerator extends SeedGenerator implements Runnable {
+    private static class ThreadedSeedGenerator extends SeedGenerator
+            implements Runnable {
         // Queue is used to collect seed bytes
         private byte[] pool;
         private int start, end, count;
@@ -245,11 +254,10 @@
         ThreadGroup seedGroup;
 
         /**
-     * The constructor is only called once to construct the one
-     * instance we actually use. It instantiates the message digest
-     * and starts the thread going.
-     */
-
+         * The constructor is only called once to construct the one
+         * instance we actually use. It instantiates the message digest
+         * and starts the thread going.
+         */
         ThreadedSeedGenerator() {
             pool = new byte[20];
             start = end = 0;
@@ -266,16 +274,18 @@
             final ThreadGroup[] finalsg = new ThreadGroup[1];
             Thread t = java.security.AccessController.doPrivileged
                 (new java.security.PrivilegedAction<Thread>() {
+                        @Override
                         public Thread run() {
                             ThreadGroup parent, group =
                                 Thread.currentThread().getThreadGroup();
-                            while ((parent = group.getParent()) != null)
+                            while ((parent = group.getParent()) != null) {
                                 group = parent;
+                            }
                             finalsg[0] = new ThreadGroup
                                 (group, "SeedGenerator ThreadGroup");
                             Thread newT = new Thread(finalsg[0],
-                                                     ThreadedSeedGenerator.this,
-                                                     "SeedGenerator Thread");
+                                ThreadedSeedGenerator.this,
+                                "SeedGenerator Thread");
                             newT.setPriority(Thread.MIN_PRIORITY);
                             newT.setDaemon(true);
                             return newT;
@@ -289,21 +299,23 @@
          * This method does the actual work. It collects random bytes and
          * pushes them into the queue.
          */
+        @Override
         final public void run() {
             try {
                 while (true) {
                     // Queue full? Wait till there's room.
                     synchronized(this) {
-                        while (count >= pool.length)
+                        while (count >= pool.length) {
                             wait();
+                        }
                     }
 
                     int counter, quanta;
                     byte v = 0;
 
                     // Spin count must not be under 64000
-                    for (counter = quanta = 0; (counter < 64000) && (quanta < 6);
-                         quanta++) {
+                    for (counter = quanta = 0;
+                            (counter < 64000) && (quanta < 6); quanta++) {
 
                         // Start some noisy threads
                         try {
@@ -313,14 +325,12 @@
                             t.start();
                         } catch (Exception e) {
                             throw new InternalError("internal error: " +
-                                                    "SeedGenerator thread creation error."
-                                    , e);
+                                "SeedGenerator thread creation error.", e);
                         }
 
                         // We wait 250milli quanta, so the minimum wait time
                         // cannot be under 250milli.
                         int latch = 0;
-                        latch = 0;
                         long l = System.currentTimeMillis() + 250;
                         while (System.currentTimeMillis() < l) {
                             synchronized(this){};
@@ -339,16 +349,16 @@
                         pool[end] = v;
                         end++;
                         count++;
-                        if (end >= pool.length)
+                        if (end >= pool.length) {
                             end = 0;
+                        }
 
                         notifyAll();
                     }
                 }
             } catch (Exception e) {
                 throw new InternalError("internal error: " +
-                                        "SeedGenerator thread generated an exception."
-                        , e);
+                    "SeedGenerator thread generated an exception.", e);
             }
         }
 
@@ -360,19 +370,20 @@
         }
 
         byte getSeedByte() {
-            byte b = 0;
+            byte b;
 
             try {
                 // Wait for it...
                 synchronized(this) {
-                    while (count <= 0)
+                    while (count <= 0) {
                         wait();
+                    }
                 }
             } catch (Exception e) {
-                if (count <= 0)
+                if (count <= 0) {
                     throw new InternalError("internal error: " +
-                                            "SeedGenerator thread generated an exception."
-                            ,e);
+                        "SeedGenerator thread generated an exception.", e);
+                }
             }
 
             synchronized(this) {
@@ -381,8 +392,9 @@
                 pool[start] = 0;
                 start++;
                 count--;
-                if (start == pool.length)
+                if (start == pool.length) {
                     start = 0;
+                }
 
                 // Notify the daemon thread, just in case it is
                 // waiting for us to make room in the queue.
@@ -430,12 +442,13 @@
          * thus adding entropy to the system load.
          * At least one instance of this class is generated for every seed byte.
          */
-
         private static class BogusThread implements Runnable {
+            @Override
             final public void run() {
                 try {
-                    for(int i = 0; i < 5; i++)
+                    for (int i = 0; i < 5; i++) {
                         Thread.sleep(50);
+                    }
                     // System.gc();
                 } catch (Exception e) {
                 }
@@ -446,7 +459,7 @@
     static class URLSeedGenerator extends SeedGenerator {
 
         private String deviceName;
-        private InputStream devRandom;
+        private InputStream seedStream;
 
         /**
          * The constructor is only called once to construct the one
@@ -462,15 +475,12 @@
             init();
         }
 
-        URLSeedGenerator() throws IOException {
-            this(SeedGenerator.URL_DEV_RANDOM);
-        }
-
         private void init() throws IOException {
             final URL device = new URL(deviceName);
             try {
-                devRandom = java.security.AccessController.doPrivileged
+                seedStream = java.security.AccessController.doPrivileged
                     (new java.security.PrivilegedExceptionAction<InputStream>() {
+                        @Override
                         public InputStream run() throws IOException {
                             /*
                              * return a FileInputStream for file URLs and
@@ -481,7 +491,8 @@
                              * can be slow to replenish.
                              */
                             if (device.getProtocol().equalsIgnoreCase("file")) {
-                                File deviceFile = getDeviceFile(device);
+                                File deviceFile =
+                                    SunEntries.getDeviceFile(device);
                                 return new FileInputStream(deviceFile);
                             } else {
                                 return device.openStream();
@@ -489,36 +500,8 @@
                         }
                     });
             } catch (Exception e) {
-                throw new IOException("Failed to open " + deviceName, e.getCause());
-            }
-        }
-
-        /*
-         * Use a URI to access this File. Previous code used a URL
-         * which is less strict on syntax. If we encounter a
-         * URISyntaxException we make best efforts for backwards
-         * compatibility. e.g. space character in deviceName string.
-         *
-         * Method called within PrivilegedExceptionAction block.
-         */
-        private File getDeviceFile(URL device) throws IOException {
-            try {
-                URI deviceURI = device.toURI();
-                if(deviceURI.isOpaque()) {
-                    // File constructor does not accept opaque URI
-                    URI localDir = new File(System.getProperty("user.dir")).toURI();
-                    String uriPath = localDir.toString() +
-                                         deviceURI.toString().substring(5);
-                    return new File(URI.create(uriPath));
-                } else {
-                    return new File(deviceURI);
-                }
-            } catch (URISyntaxException use) {
-                /*
-                 * Make best effort to access this File.
-                 * We can try using the URL path.
-                 */
-                return new File(device.getPath());
+                throw new IOException(
+                    "Failed to open " + deviceName, e.getCause());
             }
         }
 
@@ -528,19 +511,19 @@
             int read = 0;
             try {
                 while (read < len) {
-                    int count = devRandom.read(result, read, len - read);
+                    int count = seedStream.read(result, read, len - read);
                     // /dev/random blocks - should never have EOF
-                    if (count < 0)
-                        throw new InternalError("URLSeedGenerator " + deviceName +
-                                        " reached end of file");
+                    if (count < 0) {
+                        throw new InternalError(
+                            "URLSeedGenerator " + deviceName +
+                            " reached end of file");
+                    }
                     read += count;
                 }
             } catch (IOException ioe) {
                 throw new InternalError("URLSeedGenerator " + deviceName +
-                                        " generated exception: " +
-                                        ioe.getMessage(), ioe);
+                    " generated exception: " + ioe.getMessage(), ioe);
             }
         }
-
     }
 }
--- a/src/share/classes/sun/security/provider/SunEntries.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/provider/SunEntries.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, 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,8 @@
 
 package sun.security.provider;
 
+import java.io.*;
+import java.net.*;
 import java.util.Map;
 import java.security.*;
 
@@ -92,26 +94,41 @@
         // if user selected /dev/urandom, we put it before SHA1PRNG,
         // otherwise after it
         boolean nativeAvailable = NativePRNG.isAvailable();
-        boolean useUrandom = seedSource.equals(URL_DEV_URANDOM);
-        if (nativeAvailable && useUrandom) {
+        boolean useNativePRNG = seedSource.equals(URL_DEV_URANDOM) ||
+            seedSource.equals(URL_DEV_RANDOM);
+
+        if (nativeAvailable && useNativePRNG) {
             map.put("SecureRandom.NativePRNG",
                 "sun.security.provider.NativePRNG");
         }
         map.put("SecureRandom.SHA1PRNG",
              "sun.security.provider.SecureRandom");
-        if (nativeAvailable && !useUrandom) {
+        if (nativeAvailable && !useNativePRNG) {
             map.put("SecureRandom.NativePRNG",
                 "sun.security.provider.NativePRNG");
         }
 
+        if (NativePRNG.Blocking.isAvailable()) {
+            map.put("SecureRandom.NativePRNGBlocking",
+                "sun.security.provider.NativePRNG$Blocking");
+        }
+
+        if (NativePRNG.NonBlocking.isAvailable()) {
+            map.put("SecureRandom.NativePRNGNonBlocking",
+                "sun.security.provider.NativePRNG$NonBlocking");
+        }
+
         /*
          * Signature engines
          */
-        map.put("Signature.SHA1withDSA", "sun.security.provider.DSA$SHA1withDSA");
+        map.put("Signature.SHA1withDSA",
+                "sun.security.provider.DSA$SHA1withDSA");
         map.put("Signature.NONEwithDSA", "sun.security.provider.DSA$RawDSA");
         map.put("Alg.Alias.Signature.RawDSA", "NONEwithDSA");
-        map.put("Signature.SHA224withDSA", "sun.security.provider.DSA$SHA224withDSA");
-        map.put("Signature.SHA256withDSA", "sun.security.provider.DSA$SHA256withDSA");
+        map.put("Signature.SHA224withDSA",
+                "sun.security.provider.DSA$SHA224withDSA");
+        map.put("Signature.SHA256withDSA",
+                "sun.security.provider.DSA$SHA256withDSA");
 
         String dsaKeyClasses = "java.security.interfaces.DSAPublicKey" +
                 "|java.security.interfaces.DSAPrivateKey";
@@ -128,13 +145,15 @@
         map.put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA");
         map.put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
         map.put("Alg.Alias.Signature.OID.1.2.840.10040.4.3",
-            "SHA1withDSA");
+                "SHA1withDSA");
         map.put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
         map.put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA");
         map.put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA");
-        map.put("Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.1", "SHA224withDSA");
+        map.put("Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.1",
+                "SHA224withDSA");
         map.put("Alg.Alias.Signature.2.16.840.1.101.3.4.3.1", "SHA224withDSA");
-        map.put("Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.2", "SHA256withDSA");
+        map.put("Alg.Alias.Signature.OID.2.16.840.1.101.3.4.3.2",
+                "SHA256withDSA");
         map.put("Alg.Alias.Signature.2.16.840.1.101.3.4.3.2", "SHA256withDSA");
 
         /*
@@ -160,17 +179,21 @@
 
         map.put("MessageDigest.SHA-224", "sun.security.provider.SHA2$SHA224");
         map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.4", "SHA-224");
-        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.4", "SHA-224");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.4",
+                "SHA-224");
 
         map.put("MessageDigest.SHA-256", "sun.security.provider.SHA2$SHA256");
         map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
-        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.1", "SHA-256");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.1",
+                "SHA-256");
         map.put("MessageDigest.SHA-384", "sun.security.provider.SHA5$SHA384");
         map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
-        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.2", "SHA-384");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.2",
+                "SHA-384");
         map.put("MessageDigest.SHA-512", "sun.security.provider.SHA5$SHA512");
         map.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
-        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.3", "SHA-512");
+        map.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.3",
+                "SHA-512");
 
         /*
          * Algorithm Parameter Generator engines
@@ -296,6 +319,7 @@
         seedSource = AccessController.doPrivileged(
                 new PrivilegedAction<String>() {
 
+            @Override
             public String run() {
                 String egdSource = System.getProperty(PROP_EGD, "");
                 if (egdSource.length() != 0) {
@@ -314,4 +338,36 @@
         return seedSource;
     }
 
+    /*
+     * Use a URI to access this File. Previous code used a URL
+     * which is less strict on syntax. If we encounter a
+     * URISyntaxException we make best efforts for backwards
+     * compatibility. e.g. space character in deviceName string.
+     *
+     * Method called within PrivilegedExceptionAction block.
+     *
+     * Moved from SeedGenerator to avoid initialization problems with
+     * signed providers.
+     */
+    static File getDeviceFile(URL device) throws IOException {
+        try {
+            URI deviceURI = device.toURI();
+            if(deviceURI.isOpaque()) {
+                // File constructor does not accept opaque URI
+                URI localDir = new File(
+                    System.getProperty("user.dir")).toURI();
+                String uriPath = localDir.toString() +
+                                     deviceURI.toString().substring(5);
+                return new File(URI.create(uriPath));
+            } else {
+                return new File(deviceURI);
+            }
+        } catch (URISyntaxException use) {
+            /*
+             * Make best effort to access this File.
+             * We can try using the URL path.
+             */
+            return new File(device.getPath());
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/ssl/Authenticator.java	Tue Apr 16 05:11:50 2013 -0700
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2012, 2013, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.security.ssl;
+
+import java.util.Arrays;
+
+/**
+ * This class represents an SSL/TLS message authentication token,
+ * which encapsulates a sequence number and ensures that attempts to
+ * delete or reorder messages can be detected.
+ *
+ * Each SSL/TLS connection state contains a sequence number, which
+ * is maintained separately for read and write states.  The sequence
+ * number MUST be set to zero whenever a connection state is made the
+ * active state.  Sequence numbers are of type uint64 and may not
+ * exceed 2^64-1.  Sequence numbers do not wrap.  If a SSL/TLS
+ * implementation would need to wrap a sequence number, it must
+ * renegotiate instead.  A sequence number is incremented after each
+ * record: specifically, the first record transmitted under a
+ * particular connection state MUST use sequence number 0.
+ */
+class Authenticator {
+
+    // byte array containing the additional authentication information for
+    // each record
+    private final byte[] block;
+
+    // the block size of SSL v3.0:
+    // sequence number + record type + + record length
+    private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
+
+    // the block size of TLS v1.0 and later:
+    // sequence number + record type + protocol version + record length
+    private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
+
+    /**
+     * Default construct, no message authentication token is initialized.
+     *
+     * Note that this construct can only be called for null MAC
+     */
+    Authenticator() {
+        block = new byte[0];
+    }
+
+    /**
+     * Constructs the message authentication token for the specified
+     * SSL/TLS protocol.
+     */
+    Authenticator(ProtocolVersion protocolVersion) {
+        if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
+            block = new byte[BLOCK_SIZE_TLS];
+            block[9] = protocolVersion.major;
+            block[10] = protocolVersion.minor;
+        } else {
+            block = new byte[BLOCK_SIZE_SSL];
+        }
+    }
+
+    /**
+     * Checks whether the sequence number is close to wrap.
+     *
+     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
+     * Sequence numbers do not wrap. When the sequence number is near
+     * to wrap, we need to close the connection immediately.
+     *
+     * @return true if the sequence number is close to wrap
+     */
+    final boolean seqNumOverflow() {
+        /*
+         * Conservatively, we don't allow more records to be generated
+         * when there are only 2^8 sequence numbers left.
+         */
+        return (block.length != 0 &&
+                block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
+                block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
+                block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
+                block[6] == (byte)0xFF);
+    }
+
+    /**
+     * Checks whether the sequence number close to renew.
+     *
+     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
+     * Sequence numbers do not wrap.  If a TLS
+     * implementation would need to wrap a sequence number, it must
+     * renegotiate instead.
+     *
+     * @return true if the sequence number is huge enough to renew
+     */
+    final boolean seqNumIsHuge() {
+        /*
+         * Conservatively, we should ask for renegotiation when there are
+         * only 2^48 sequence numbers left.
+         */
+        return (block.length != 0 &&
+                block[0] == (byte)0xFF && block[1] == (byte)0xFF);
+    }
+
+    /**
+     * Gets the current sequence number.
+     *
+     * @return the byte array of the current sequence number
+     */
+    final byte[] sequenceNumber() {
+        return Arrays.copyOf(block, 8);
+    }
+
+    /**
+     * Acquires the current message authentication information with the
+     * specified record type and fragment length, and then increases the
+     * sequence number.
+     *
+     * @param  type the record type
+     * @param  length the fragment of the record
+     * @return the byte array of the current message authentication information
+     */
+    final byte[] acquireAuthenticationBytes(byte type, int length) {
+        byte[] copy = block.clone();
+
+        if (block.length != 0) {
+            copy[8] = type;
+            copy[copy.length - 2] = (byte)(length >> 8);
+            copy[copy.length - 1] = (byte)(length);
+
+            /*
+             * Increase the sequence number in the block array
+             * it is a 64-bit number stored in big-endian format
+             */
+            int k = 7;
+            while ((k >= 0) && (++block[k] == 0)) {
+                k--;
+            }
+        }
+
+        return copy;
+    }
+
+}
--- a/src/share/classes/sun/security/ssl/CipherBox.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/CipherBox.java	Tue Apr 16 05:11:50 2013 -0700
@@ -29,15 +29,18 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.util.Hashtable;
+import java.util.Arrays;
 
 import java.security.*;
 import javax.crypto.*;
 import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.GCMParameterSpec;
 
 import java.nio.*;
 
 import sun.security.ssl.CipherSuite.*;
 import static sun.security.ssl.CipherSuite.*;
+import static sun.security.ssl.CipherSuite.CipherType.*;
 
 import sun.misc.HexDumpEncoder;
 
@@ -102,19 +105,40 @@
     private final Cipher cipher;
 
     /**
-     * Cipher blocksize, 0 for stream ciphers
-     */
-    private int blockSize;
-
-    /**
      * secure random
      */
     private SecureRandom random;
 
     /**
-     * Is the cipher of CBC mode?
+     * fixed IV, the implicit nonce of AEAD cipher suite, only apply to
+     * AEAD cipher suites
+     */
+    private final byte[] fixedIv;
+
+    /**
+     * the key, reserved only for AEAD cipher initialization
+     */
+    private final Key key;
+
+    /**
+     * the operation mode, reserved for AEAD cipher initialization
      */
-    private final boolean isCBCMode;
+    private final int mode;
+
+    /**
+     * the authentication tag size, only apply to AEAD cipher suites
+     */
+    private final int tagSize;
+
+    /**
+     * the record IV length, only apply to AEAD cipher suites
+     */
+    private final int recordIvSize;
+
+    /**
+     * cipher type
+     */
+    private final CipherType cipherType;
 
     /**
      * Fixed masks of various block size, as the initial decryption IVs
@@ -132,7 +156,13 @@
     private CipherBox() {
         this.protocolVersion = ProtocolVersion.DEFAULT;
         this.cipher = null;
-        this.isCBCMode = false;
+        this.cipherType = STREAM_CIPHER;
+        this.fixedIv = new byte[0];
+        this.key = null;
+        this.mode = Cipher.ENCRYPT_MODE;    // choose at random
+        this.random = null;
+        this.tagSize = 0;
+        this.recordIvSize = 0;
     }
 
     /**
@@ -147,13 +177,13 @@
         try {
             this.protocolVersion = protocolVersion;
             this.cipher = JsseJce.getCipher(bulkCipher.transformation);
-            int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
+            this.mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
 
             if (random == null) {
                 random = JsseJce.getSecureRandom();
             }
             this.random = random;
-            this.isCBCMode = bulkCipher.isCBCMode;
+            this.cipherType = bulkCipher.cipherType;
 
             /*
              * RFC 4346 recommends two algorithms used to generated the
@@ -171,14 +201,40 @@
                 iv = getFixedMask(bulkCipher.ivSize);
             }
 
-            cipher.init(mode, key, iv, random);
+            if (cipherType == AEAD_CIPHER) {
+                // AEAD must completely initialize the cipher for each packet,
+                // and so we save initialization parameters for packet
+                // processing time.
+
+                // Set the tag size for AEAD cipher
+                tagSize = bulkCipher.tagSize;
+
+                // Reserve the key for AEAD cipher initialization
+                this.key = key;
+
+                fixedIv = iv.getIV();
+                if (fixedIv == null ||
+                        fixedIv.length != bulkCipher.fixedIvSize) {
+                    throw new RuntimeException("Improper fixed IV for AEAD");
+                }
 
-            // Do not call getBlockSize until after init()
-            // otherwise we would disrupt JCE delayed provider selection
-            blockSize = cipher.getBlockSize();
-            // some providers implement getBlockSize() incorrectly
-            if (blockSize == 1) {
-                blockSize = 0;
+                // Set the record IV length for AEAD cipher
+                recordIvSize = bulkCipher.ivSize - bulkCipher.fixedIvSize;
+
+                // DON'T initialize the cipher for AEAD!
+            } else {
+                // CBC only requires one initialization during its lifetime
+                // (future packets/IVs set the proper CBC state), so we can
+                // initialize now.
+
+                // Zeroize the variables that only apply to AEAD cipher
+                this.tagSize = 0;
+                this.fixedIv = new byte[0];
+                this.recordIvSize = 0;
+                this.key = null;
+
+                // Initialize the cipher
+                cipher.init(mode, key, iv, random);
             }
         } catch (NoSuchAlgorithmException e) {
             throw e;
@@ -235,26 +291,11 @@
         }
 
         try {
-            if (blockSize != 0) {
-                // TLSv1.1 needs a IV block
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    // generate a random number
-                    byte[] prefix = new byte[blockSize];
-                    random.nextBytes(prefix);
-
-                    // move forward the plaintext
-                    System.arraycopy(buf, offset,
-                                     buf, offset + prefix.length, len);
-
-                    // prefix the plaintext
-                    System.arraycopy(prefix, 0,
-                                     buf, offset, prefix.length);
-
-                    len += prefix.length;
-                }
-
+            int blockSize = cipher.getBlockSize();
+            if (cipherType == BLOCK_CIPHER) {
                 len = addPadding(buf, offset, len, blockSize);
             }
+
             if (debug != null && Debug.isOn("plaintext")) {
                 try {
                     HexDumpEncoder hd = new HexDumpEncoder();
@@ -267,14 +308,28 @@
                         System.out);
                 } catch (IOException e) { }
             }
-            int newLen = cipher.update(buf, offset, len, buf, offset);
-            if (newLen != len) {
-                // catch BouncyCastle buffering error
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
+
+
+            if (cipherType == AEAD_CIPHER) {
+                try {
+                    return cipher.doFinal(buf, offset, len, buf, offset);
+                } catch (IllegalBlockSizeException | BadPaddingException ibe) {
+                    // unlikely to happen
+                    throw new RuntimeException(
+                        "Cipher error in AEAD mode in JCE provider " +
+                        cipher.getProvider().getName(), ibe);
+                }
+            } else {
+                int newLen = cipher.update(buf, offset, len, buf, offset);
+                if (newLen != len) {
+                    // catch BouncyCastle buffering error
+                    throw new RuntimeException("Cipher buffering error " +
+                        "in JCE provider " + cipher.getProvider().getName());
+                }
+                return newLen;
             }
-            return newLen;
         } catch (ShortBufferException e) {
+            // unlikely to happen, we should have enough buffer space here
             throw new ArrayIndexOutOfBoundsException(e.toString());
         }
     }
@@ -288,7 +343,7 @@
      * set to last position padded/encrypted.  The limit may have changed
      * because of the added padding bytes.
      */
-    int encrypt(ByteBuffer bb) {
+    int encrypt(ByteBuffer bb, int outLimit) {
 
         int len = bb.remaining();
 
@@ -297,66 +352,71 @@
             return len;
         }
 
-        try {
-            int pos = bb.position();
+        int pos = bb.position();
 
-            if (blockSize != 0) {
-                // TLSv1.1 needs a IV block
-                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
-                    // generate a random number
-                    byte[] prefix = new byte[blockSize];
-                    random.nextBytes(prefix);
+        int blockSize = cipher.getBlockSize();
+        if (cipherType == BLOCK_CIPHER) {
+            // addPadding adjusts pos/limit
+            len = addPadding(bb, blockSize);
+            bb.position(pos);
+        }
 
-                    // move forward the plaintext
-                    byte[] buf = null;
-                    int limit = bb.limit();
-                    if (bb.hasArray()) {
-                        int arrayOffset = bb.arrayOffset();
-                        buf = bb.array();
-                        System.arraycopy(buf, arrayOffset + pos,
-                            buf, arrayOffset + pos + prefix.length,
-                            limit - pos);
-                        bb.limit(limit + prefix.length);
-                    } else {
-                        buf = new byte[limit - pos];
-                        bb.get(buf, 0, limit - pos);
-                        bb.position(pos + prefix.length);
-                        bb.limit(limit + prefix.length);
-                        bb.put(buf);
-                    }
-                    bb.position(pos);
+        if (debug != null && Debug.isOn("plaintext")) {
+            try {
+                HexDumpEncoder hd = new HexDumpEncoder();
+
+                System.out.println(
+                    "Padded plaintext before ENCRYPTION:  len = "
+                    + len);
+                hd.encodeBuffer(bb.duplicate(), System.out);
+
+            } catch (IOException e) { }
+        }
 
-                    // prefix the plaintext
-                    bb.put(prefix);
-                    bb.position(pos);
+        /*
+         * Encrypt "in-place".  This does not add its own padding.
+         */
+        ByteBuffer dup = bb.duplicate();
+        if (cipherType == AEAD_CIPHER) {
+            try {
+                int outputSize = cipher.getOutputSize(dup.remaining());
+                if (outputSize > bb.remaining()) {
+                    // need to expand the limit of the output buffer for
+                    // the authentication tag.
+                    //
+                    // DON'T worry about the buffer's capacity, we have
+                    // reserved space for the authentication tag.
+                    if (outLimit < pos + outputSize) {
+                        // unlikely to happen
+                        throw new ShortBufferException(
+                                    "need more space in output buffer");
+                    }
+                    bb.limit(pos + outputSize);
                 }
-
-                // addPadding adjusts pos/limit
-                len = addPadding(bb, blockSize);
-                bb.position(pos);
+                int newLen = cipher.doFinal(dup, bb);
+                if (newLen != outputSize) {
+                    throw new RuntimeException(
+                            "Cipher buffering error in JCE provider " +
+                            cipher.getProvider().getName());
+                }
+                return newLen;
+            } catch (IllegalBlockSizeException |
+                           BadPaddingException | ShortBufferException ibse) {
+                // unlikely to happen
+                throw new RuntimeException(
+                        "Cipher error in AEAD mode in JCE provider " +
+                        cipher.getProvider().getName(), ibse);
             }
-            if (debug != null && Debug.isOn("plaintext")) {
-                try {
-                    HexDumpEncoder hd = new HexDumpEncoder();
-
-                    System.out.println(
-                        "Padded plaintext before ENCRYPTION:  len = "
-                        + len);
-                    hd.encodeBuffer(bb, System.out);
-
-                } catch (IOException e) { }
-                /*
-                 * reset back to beginning
-                 */
-                bb.position(pos);
+        } else {
+            int newLen;
+            try {
+                newLen = cipher.update(dup, bb);
+            } catch (ShortBufferException sbe) {
+                // unlikely to happen
+                throw new RuntimeException("Cipher buffering error " +
+                    "in JCE provider " + cipher.getProvider().getName());
             }
 
-            /*
-             * Encrypt "in-place".  This does not add its own padding.
-             */
-            ByteBuffer dup = bb.duplicate();
-            int newLen = cipher.update(dup, bb);
-
             if (bb.position() != dup.position()) {
                 throw new RuntimeException("bytebuffer padding error");
             }
@@ -367,10 +427,6 @@
                     "in JCE provider " + cipher.getProvider().getName());
             }
             return newLen;
-        } catch (ShortBufferException e) {
-            RuntimeException exc = new RuntimeException(e.toString());
-            exc.initCause(e);
-            throw exc;
         }
     }
 
@@ -399,11 +455,23 @@
         }
 
         try {
-            int newLen = cipher.update(buf, offset, len, buf, offset);
-            if (newLen != len) {
-                // catch BouncyCastle buffering error
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
+            int newLen;
+            if (cipherType == AEAD_CIPHER) {
+                try {
+                    newLen = cipher.doFinal(buf, offset, len, buf, offset);
+                } catch (IllegalBlockSizeException ibse) {
+                    // unlikely to happen
+                    throw new RuntimeException(
+                        "Cipher error in AEAD mode in JCE provider " +
+                        cipher.getProvider().getName(), ibse);
+                }
+            } else {
+                newLen = cipher.update(buf, offset, len, buf, offset);
+                if (newLen != len) {
+                    // catch BouncyCastle buffering error
+                    throw new RuntimeException("Cipher buffering error " +
+                        "in JCE provider " + cipher.getProvider().getName());
+                }
             }
             if (debug != null && Debug.isOn("plaintext")) {
                 try {
@@ -418,7 +486,8 @@
                 } catch (IOException e) { }
             }
 
-            if (blockSize != 0) {
+            if (cipherType == BLOCK_CIPHER) {
+                int blockSize = cipher.getBlockSize();
                 newLen = removePadding(
                     buf, offset, newLen, tagLen, blockSize, protocolVersion);
 
@@ -426,16 +495,11 @@
                     if (newLen < blockSize) {
                         throw new BadPaddingException("invalid explicit IV");
                     }
-
-                    // discards the first cipher block, the IV component.
-                    System.arraycopy(buf, offset + blockSize,
-                                     buf, offset, newLen - blockSize);
-
-                    newLen -= blockSize;
                 }
             }
             return newLen;
         } catch (ShortBufferException e) {
+            // unlikely to happen, we should have enough buffer space here
             throw new ArrayIndexOutOfBoundsException(e.toString());
         }
     }
@@ -465,13 +529,28 @@
              */
             int pos = bb.position();
             ByteBuffer dup = bb.duplicate();
-            int newLen = cipher.update(dup, bb);
-            if (newLen != len) {
-                // catch BouncyCastle buffering error
-                throw new RuntimeException("Cipher buffering error " +
-                    "in JCE provider " + cipher.getProvider().getName());
+            int newLen;
+            if (cipherType == AEAD_CIPHER) {
+                try {
+                    newLen = cipher.doFinal(dup, bb);
+                } catch (IllegalBlockSizeException ibse) {
+                    // unlikely to happen
+                    throw new RuntimeException(
+                        "Cipher error in AEAD mode \"" + ibse.getMessage() +
+                        " \"in JCE provider " + cipher.getProvider().getName());
+                }
+            } else {
+                newLen = cipher.update(dup, bb);
+                if (newLen != len) {
+                    // catch BouncyCastle buffering error
+                    throw new RuntimeException("Cipher buffering error " +
+                        "in JCE provider " + cipher.getProvider().getName());
+                }
             }
 
+            // reset the limit to the end of the decryted data
+            bb.limit(pos + newLen);
+
             if (debug != null && Debug.isOn("plaintext")) {
                 try {
                     HexDumpEncoder hd = new HexDumpEncoder();
@@ -488,44 +567,25 @@
             /*
              * Remove the block padding.
              */
-            if (blockSize != 0) {
+            if (cipherType == BLOCK_CIPHER) {
+                int blockSize = cipher.getBlockSize();
                 bb.position(pos);
-                newLen = removePadding(
-                    bb, tagLen, blockSize, protocolVersion);
+                newLen = removePadding(bb, tagLen, blockSize, protocolVersion);
 
+                // check the explicit IV of TLS v1.1 or later
                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
                     if (newLen < blockSize) {
                         throw new BadPaddingException("invalid explicit IV");
                     }
 
-                    // discards the first cipher block, the IV component.
-                    byte[] buf = null;
-                    int limit = bb.limit();
-                    if (bb.hasArray()) {
-                        int arrayOffset = bb.arrayOffset();
-                        buf = bb.array();
-                        System.arraycopy(buf, arrayOffset + pos + blockSize,
-                            buf, arrayOffset + pos, limit - pos - blockSize);
-                        bb.limit(limit - blockSize);
-                    } else {
-                        buf = new byte[limit - pos - blockSize];
-                        bb.position(pos + blockSize);
-                        bb.get(buf);
-                        bb.position(pos);
-                        bb.put(buf);
-                        bb.limit(limit - blockSize);
-                    }
-
                     // reset the position to the end of the decrypted data
-                    limit = bb.limit();
-                    bb.position(limit);
+                    bb.position(bb.limit());
                 }
             }
             return newLen;
         } catch (ShortBufferException e) {
-            RuntimeException exc = new RuntimeException(e.toString());
-            exc.initCause(e);
-            throw exc;
+            // unlikely to happen, we should have enough buffer space here
+            throw new ArrayIndexOutOfBoundsException(e.toString());
         }
     }
 
@@ -766,8 +826,8 @@
                 // ignore return value.
                 cipher.doFinal();
             }
-        } catch (GeneralSecurityException e) {
-            // swallow for now.
+        } catch (Exception e) {
+            // swallow all types of exceptions.
         }
     }
 
@@ -777,10 +837,19 @@
      * @return true if the cipher use CBC mode, false otherwise.
      */
     boolean isCBCMode() {
-        return isCBCMode;
+        return cipherType == BLOCK_CIPHER;
     }
 
-    /**
+    /*
+     * Does the cipher use AEAD mode?
+     *
+     * @return true if the cipher use AEAD mode, false otherwise.
+     */
+    boolean isAEADMode() {
+        return cipherType == AEAD_CIPHER;
+    }
+
+    /*
      * Is the cipher null?
      *
      * @return true if the cipher is null, false otherwise.
@@ -789,6 +858,226 @@
         return cipher == null;
     }
 
+    /*
+     * Gets the explicit nonce/IV size of the cipher.
+     *
+     * The returned value is the SecurityParameters.record_iv_length in
+     * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
+     * size of explicit nonce for AEAD mode.
+     *
+     * @return the explicit nonce size of the cipher.
+     */
+    int getExplicitNonceSize() {
+        switch (cipherType) {
+            case BLOCK_CIPHER:
+                // For block ciphers, the explicit IV length is of length
+                // SecurityParameters.record_iv_length, which is equal to
+                // the SecurityParameters.block_size.
+                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                    return cipher.getBlockSize();
+                }
+                break;
+            case AEAD_CIPHER:
+                return recordIvSize;
+                        // It is also the length of sequence number, which is
+                        // used as the nonce_explicit for AEAD cipher suites.
+        }
+
+        return 0;
+    }
+
+    /*
+     * Applies the explicit nonce/IV to this cipher. This method is used to
+     * decrypt an SSL/TLS input record.
+     *
+     * The returned value is the SecurityParameters.record_iv_length in
+     * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
+     * size of explicit nonce for AEAD mode.
+     *
+     * @param  authenticator the authenticator to get the additional
+     *         authentication data
+     * @param  contentType the content type of the input record
+     * @param  bb the byte buffer to get the explicit nonce from
+     *
+     * @return the explicit nonce size of the cipher.
+     */
+    int applyExplicitNonce(Authenticator authenticator, byte contentType,
+            ByteBuffer bb) throws BadPaddingException {
+        switch (cipherType) {
+            case BLOCK_CIPHER:
+                // sanity check length of the ciphertext
+                int tagLen = (authenticator instanceof MAC) ?
+                                    ((MAC)authenticator).MAClen() : 0;
+                if (tagLen != 0) {
+                    if (!sanityCheck(tagLen, bb.remaining())) {
+                        throw new BadPaddingException(
+                                "ciphertext sanity check failed");
+                    }
+                }
+
+                // For block ciphers, the explicit IV length is of length
+                // SecurityParameters.record_iv_length, which is equal to
+                // the SecurityParameters.block_size.
+                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                    return cipher.getBlockSize();
+                }
+                break;
+            case AEAD_CIPHER:
+                if (bb.remaining() < (recordIvSize + tagSize)) {
+                    throw new BadPaddingException(
+                                        "invalid AEAD cipher fragment");
+                }
+
+                // initialize the AEAD cipher for the unique IV
+                byte[] iv = Arrays.copyOf(fixedIv,
+                                    fixedIv.length + recordIvSize);
+                bb.get(iv, fixedIv.length, recordIvSize);
+                bb.position(bb.position() - recordIvSize);
+                GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
+                try {
+                    cipher.init(mode, key, spec, random);
+                } catch (InvalidKeyException |
+                            InvalidAlgorithmParameterException ikae) {
+                    // unlikely to happen
+                    throw new RuntimeException(
+                                "invalid key or spec in GCM mode", ikae);
+                }
+
+                // update the additional authentication data
+                byte[] aad = authenticator.acquireAuthenticationBytes(
+                        contentType, bb.remaining() - recordIvSize - tagSize);
+                cipher.updateAAD(aad);
+
+                return recordIvSize;
+                        // It is also the length of sequence number, which is
+                        // used as the nonce_explicit for AEAD cipher suites.
+        }
+
+       return 0;
+    }
+
+    /*
+     * Applies the explicit nonce/IV to this cipher. This method is used to
+     * decrypt an SSL/TLS input record.
+     *
+     * The returned value is the SecurityParameters.record_iv_length in
+     * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
+     * size of explicit nonce for AEAD mode.
+     *
+     * @param  authenticator the authenticator to get the additional
+     *         authentication data
+     * @param  contentType the content type of the input record
+     * @param  buf the byte array to get the explicit nonce from
+     * @param  offset the offset of the byte buffer
+     * @param  cipheredLength the ciphered fragment length of the output
+     *         record, it is the TLSCiphertext.length in RFC 4346/5246.
+     *
+     * @return the explicit nonce size of the cipher.
+     */
+    int applyExplicitNonce(Authenticator authenticator,
+            byte contentType, byte[] buf, int offset,
+            int cipheredLength) throws BadPaddingException {
+
+        ByteBuffer bb = ByteBuffer.wrap(buf, offset, cipheredLength);
+
+        return applyExplicitNonce(authenticator, contentType, bb);
+    }
+
+    /*
+     * Creates the explicit nonce/IV to this cipher. This method is used to
+     * encrypt an SSL/TLS output record.
+     *
+     * The size of the returned array is the SecurityParameters.record_iv_length
+     * in RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
+     * size of explicit nonce for AEAD mode.
+     *
+     * @param  authenticator the authenticator to get the additional
+     *         authentication data
+     * @param  contentType the content type of the input record
+     * @param  fragmentLength the fragment length of the output record, it is
+     *         the TLSCompressed.length in RFC 4346/5246.
+     *
+     * @return the explicit nonce of the cipher.
+     */
+    byte[] createExplicitNonce(Authenticator authenticator,
+            byte contentType, int fragmentLength) {
+
+        byte[] nonce = new byte[0];
+        switch (cipherType) {
+            case BLOCK_CIPHER:
+                if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
+                    // For block ciphers, the explicit IV length is of length
+                    // SecurityParameters.record_iv_length, which is equal to
+                    // the SecurityParameters.block_size.
+                    //
+                    // Generate a random number as the explicit IV parameter.
+                    nonce = new byte[cipher.getBlockSize()];
+                    random.nextBytes(nonce);
+                }
+                break;
+            case AEAD_CIPHER:
+                // To be unique and aware of overflow-wrap, sequence number
+                // is used as the nonce_explicit of AEAD cipher suites.
+                nonce = authenticator.sequenceNumber();
+
+                // initialize the AEAD cipher for the unique IV
+                byte[] iv = Arrays.copyOf(fixedIv,
+                                            fixedIv.length + nonce.length);
+                System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
+                GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
+                try {
+                    cipher.init(mode, key, spec, random);
+                } catch (InvalidKeyException |
+                            InvalidAlgorithmParameterException ikae) {
+                    // unlikely to happen
+                    throw new RuntimeException(
+                                "invalid key or spec in GCM mode", ikae);
+                }
+
+                // update the additional authentication data
+                byte[] aad = authenticator.acquireAuthenticationBytes(
+                                                contentType, fragmentLength);
+                cipher.updateAAD(aad);
+                break;
+        }
+
+        return nonce;
+    }
+
+    /*
+     * Is this cipher available?
+     *
+     * This method can only be called by CipherSuite.BulkCipher.isAvailable()
+     * to test the availability of a cipher suites.  Please DON'T use it in
+     * other places, otherwise, the behavior may be unexpected because we may
+     * initialize AEAD cipher improperly in the method.
+     */
+    Boolean isAvailable() {
+        // We won't know whether a cipher for a particular key size is
+        // available until the cipher is successfully initialized.
+        //
+        // We do not initialize AEAD cipher in the constructor.  Need to
+        // initialize the cipher to ensure that the AEAD mode for a
+        // particular key size is supported.
+        if (cipherType == AEAD_CIPHER) {
+            try {
+                Authenticator authenticator =
+                    new Authenticator(protocolVersion);
+                byte[] nonce = authenticator.sequenceNumber();
+                byte[] iv = Arrays.copyOf(fixedIv,
+                                            fixedIv.length + nonce.length);
+                System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
+                GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
+
+                cipher.init(mode, key, spec, random);
+            } catch (Exception e) {
+                return Boolean.FALSE;
+            }
+        }   // Otherwise, we have initialized the cipher in the constructor.
+
+        return Boolean.TRUE;
+    }
+
     /**
      * Sanity check the length of a fragment before decryption.
      *
@@ -802,11 +1091,12 @@
      *
      * @return true if the length of a fragment matches above requirements
      */
-    boolean sanityCheck(int tagLen, int fragmentLen) {
-        if (!isCBCMode) {
+    private boolean sanityCheck(int tagLen, int fragmentLen) {
+        if (!isCBCMode()) {
             return fragmentLen >= tagLen;
         }
 
+        int blockSize = cipher.getBlockSize();
         if ((fragmentLen % blockSize) == 0) {
             int minimal = tagLen + 1;
             minimal = (minimal >= blockSize) ? minimal : blockSize;
--- a/src/share/classes/sun/security/ssl/CipherSuite.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/CipherSuite.java	Tue Apr 16 05:11:50 2013 -0700
@@ -33,12 +33,14 @@
 import java.security.SecureRandom;
 import java.security.KeyManagementException;
 
+import javax.crypto.Cipher;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
 import static sun.security.ssl.CipherSuite.KeyExchange.*;
 import static sun.security.ssl.CipherSuite.PRF.*;
+import static sun.security.ssl.CipherSuite.CipherType.*;
 import static sun.security.ssl.JsseJce.*;
 
 /**
@@ -135,7 +137,9 @@
         this.keyExchange = keyExchange;
         this.cipher = cipher;
         this.exportable = cipher.exportable;
-        if (name.endsWith("_MD5")) {
+        if (cipher.cipherType == CipherType.AEAD_CIPHER) {
+            macAlg = M_NULL;
+        } else if (name.endsWith("_MD5")) {
             macAlg = M_MD5;
         } else if (name.endsWith("_SHA")) {
             macAlg = M_SHA;
@@ -385,6 +389,12 @@
         }
     }
 
+    static enum CipherType {
+        STREAM_CIPHER,         // null or stream cipher
+        BLOCK_CIPHER,          // block cipher in CBC mode
+        AEAD_CIPHER            // AEAD cipher
+    }
+
     /**
      * An SSL/TLS bulk cipher algorithm. One instance per combination of
      * cipher and key length.
@@ -417,14 +427,26 @@
         // for non-exportable ciphers, this is the same as keySize
         final int expandedKeySize;
 
-        // size of the IV (also block size)
+        // size of the IV
         final int ivSize;
 
+        // size of fixed IV
+        //
+        // record_iv_length = ivSize - fixedIvSize
+        final int fixedIvSize;
+
         // exportable under 512/40 bit rules
         final boolean exportable;
 
         // Is the cipher algorithm of Cipher Block Chaining (CBC) mode?
-        final boolean isCBCMode;
+        final CipherType cipherType;
+
+        // size of the authentication tag, only applicable to cipher suites in
+        // Galois Counter Mode (GCM)
+        //
+        // As far as we know, all supported GCM cipher suites use 128-bits
+        // authentication tags.
+        final int tagSize = 16;
 
         // The secure random used to detect the cipher availability.
         private final static SecureRandom secureRandom;
@@ -437,32 +459,34 @@
             }
         }
 
-        BulkCipher(String transformation, int keySize,
-                int expandedKeySize, int ivSize, boolean allowed) {
+        BulkCipher(String transformation, CipherType cipherType, int keySize,
+                int expandedKeySize, int ivSize,
+                int fixedIvSize, boolean allowed) {
+
             this.transformation = transformation;
             String[] splits = transformation.split("/");
             this.algorithm = splits[0];
-            this.isCBCMode =
-                splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
+            this.cipherType = cipherType;
             this.description = this.algorithm + "/" + (keySize << 3);
             this.keySize = keySize;
             this.ivSize = ivSize;
+            this.fixedIvSize = fixedIvSize;
             this.allowed = allowed;
 
             this.expandedKeySize = expandedKeySize;
             this.exportable = true;
         }
 
-        BulkCipher(String transformation, int keySize,
-                int ivSize, boolean allowed) {
+        BulkCipher(String transformation, CipherType cipherType, int keySize,
+                int ivSize, int fixedIvSize, boolean allowed) {
             this.transformation = transformation;
             String[] splits = transformation.split("/");
             this.algorithm = splits[0];
-            this.isCBCMode =
-                splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
+            this.cipherType = cipherType;
             this.description = this.algorithm + "/" + (keySize << 3);
             this.keySize = keySize;
             this.ivSize = ivSize;
+            this.fixedIvSize = fixedIvSize;
             this.allowed = allowed;
 
             this.expandedKeySize = keySize;
@@ -486,16 +510,20 @@
          * Test if this bulk cipher is available. For use by CipherSuite.
          *
          * Currently all supported ciphers except AES are always available
-         * via the JSSE internal implementations. We also assume AES/128
-         * is always available since it is shipped with the SunJCE provider.
-         * However, AES/256 is unavailable when the default JCE policy
-         * jurisdiction files are installed because of key length restrictions.
+         * via the JSSE internal implementations. We also assume AES/128 of
+         * CBC mode is always available since it is shipped with the SunJCE
+         * provider.  However, AES/256 is unavailable when the default JCE
+         * policy jurisdiction files are installed because of key length
+         * restrictions, and AEAD is unavailable when the underlying providers
+         * do not support AEAD/GCM mode.
          */
         boolean isAvailable() {
             if (allowed == false) {
                 return false;
             }
-            if (this == B_AES_256) {
+
+            if ((this == B_AES_256) ||
+                    (this.cipherType == CipherType.AEAD_CIPHER)) {
                 return isAvailable(this);
             }
 
@@ -513,19 +541,50 @@
         private static synchronized boolean isAvailable(BulkCipher cipher) {
             Boolean b = availableCache.get(cipher);
             if (b == null) {
-                try {
-                    SecretKey key = new SecretKeySpec
-                        (new byte[cipher.expandedKeySize], cipher.algorithm);
-                    IvParameterSpec iv =
-                        new IvParameterSpec(new byte[cipher.ivSize]);
-                    cipher.newCipher(ProtocolVersion.DEFAULT,
+                int keySizeInBits = cipher.keySize * 8;
+                if (keySizeInBits > 128) {    // need the JCE unlimited
+                                               // strength jurisdiction policy
+                    try {
+                        if (Cipher.getMaxAllowedKeyLength(
+                                cipher.transformation) < keySizeInBits) {
+                            b = Boolean.FALSE;
+                        }
+                    } catch (Exception e) {
+                        b = Boolean.FALSE;
+                    }
+                }
+
+                if (b == null) {
+                    b = Boolean.FALSE;          // may be reset to TRUE if
+                                                // the cipher is available
+                    CipherBox temporary = null;
+                    try {
+                        SecretKey key = new SecretKeySpec(
+                                            new byte[cipher.expandedKeySize],
+                                            cipher.algorithm);
+                        IvParameterSpec iv;
+                        if (cipher.cipherType == CipherType.AEAD_CIPHER) {
+                            iv = new IvParameterSpec(
+                                            new byte[cipher.fixedIvSize]);
+                        } else {
+                            iv = new IvParameterSpec(new byte[cipher.ivSize]);
+                        }
+                        temporary = cipher.newCipher(
+                                            ProtocolVersion.DEFAULT,
                                             key, iv, secureRandom, true);
-                    b = Boolean.TRUE;
-                } catch (NoSuchAlgorithmException e) {
-                    b = Boolean.FALSE;
+                        b = temporary.isAvailable();
+                    } catch (NoSuchAlgorithmException e) {
+                        // not available
+                    } finally {
+                        if (temporary != null) {
+                            temporary.dispose();
+                        }
+                    }
                 }
+
                 availableCache.put(cipher, b);
             }
+
             return b.booleanValue();
         }
 
@@ -582,27 +641,31 @@
 
     // export strength ciphers
     final static BulkCipher B_NULL    =
-                        new BulkCipher("NULL",         0,  0, 0, true);
+        new BulkCipher("NULL",          STREAM_CIPHER,    0,  0,  0, 0, true);
     final static BulkCipher B_RC4_40  =
-                        new BulkCipher(CIPHER_RC4,     5, 16, 0, true);
+        new BulkCipher(CIPHER_RC4,      STREAM_CIPHER,    5, 16,  0, 0, true);
     final static BulkCipher B_RC2_40  =
-                        new BulkCipher("RC2",          5, 16, 8, false);
+        new BulkCipher("RC2",           BLOCK_CIPHER,     5, 16,  8, 0, false);
     final static BulkCipher B_DES_40  =
-                        new BulkCipher(CIPHER_DES,     5,  8, 8, true);
+        new BulkCipher(CIPHER_DES,      BLOCK_CIPHER,     5,  8,  8, 0, true);
 
     // domestic strength ciphers
     final static BulkCipher B_RC4_128 =
-                        new BulkCipher(CIPHER_RC4,     16,  0, true);
+        new BulkCipher(CIPHER_RC4,      STREAM_CIPHER,   16,  0,  0, true);
     final static BulkCipher B_DES     =
-                        new BulkCipher(CIPHER_DES,      8,  8, true);
+        new BulkCipher(CIPHER_DES,      BLOCK_CIPHER,     8,  8,  0, true);
     final static BulkCipher B_3DES    =
-                        new BulkCipher(CIPHER_3DES,    24,  8, true);
+        new BulkCipher(CIPHER_3DES,     BLOCK_CIPHER,    24,  8,  0, true);
     final static BulkCipher B_IDEA    =
-                        new BulkCipher("IDEA",         16,  8, false);
+        new BulkCipher("IDEA",          BLOCK_CIPHER,    16,  8,  0, false);
     final static BulkCipher B_AES_128 =
-                        new BulkCipher(CIPHER_AES,     16, 16, true);
+        new BulkCipher(CIPHER_AES,      BLOCK_CIPHER,    16, 16,  0, true);
     final static BulkCipher B_AES_256 =
-                        new BulkCipher(CIPHER_AES,     32, 16, true);
+        new BulkCipher(CIPHER_AES,      BLOCK_CIPHER,    32, 16,  0, true);
+    final static BulkCipher B_AES_128_GCM =
+        new BulkCipher(CIPHER_AES_GCM,  AEAD_CIPHER,     16, 12,  4, true);
+    final static BulkCipher B_AES_256_GCM =
+        new BulkCipher(CIPHER_AES_GCM,  AEAD_CIPHER,     32, 12,  4, true);
 
     // MACs
     final static MacAlg M_NULL    = new MacAlg("NULL",     0,   0,   0);
@@ -902,11 +965,13 @@
          * Definition of the CipherSuites that are enabled by default.
          * They are listed in preference order, most preferred first, using
          * the following criteria:
-         * 1. Prefer the stronger buld cipher, in the order of AES_256,
-         *    AES_128, RC-4, 3DES-EDE.
-         * 2. Prefer the stronger MAC algorithm, in the order of SHA384,
+         * 1. Prefer Suite B compliant cipher suites, see RFC6460 (To be
+         *    changed later, see below).
+         * 2. Prefer the stronger bulk cipher, in the order of AES_256(GCM),
+         *    AES_128(GCM), AES_256, AES_128, RC-4, 3DES-EDE.
+         * 3. Prefer the stronger MAC algorithm, in the order of SHA384,
          *    SHA256, SHA, MD5.
-         * 3. Prefer the better performance of key exchange and digital
+         * 4. Prefer the better performance of key exchange and digital
          *    signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
          *    RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS.
          */
@@ -919,6 +984,16 @@
 
         //  ID           Key Exchange   Cipher     A  obs  suprt  PRF
         //  ======       ============   =========  =  ===  =====  ========
+
+
+        // Placeholder for cipher suites in GCM mode.
+        //
+        // For better compatibility and interoperability, we decrease the
+        // priority of cipher suites in GCM mode for a while as GCM
+        // technologies mature in the industry.  Eventually we'll move
+        // the GCM suites here.
+
+        // AES_256(CBC)
         add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
             0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
         add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
@@ -949,6 +1024,7 @@
         add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
             0x0038, --p, K_DHE_DSS,     B_AES_256, T);
 
+        // AES_128(CBC)
         add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
             0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
         add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
@@ -979,6 +1055,7 @@
         add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
             0x0032, --p, K_DHE_DSS,     B_AES_128, T);
 
+        // RC-4
         add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
             0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
         add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
@@ -990,6 +1067,51 @@
         add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
             0xC00C, --p, K_ECDH_RSA,    B_RC4_128, N);
 
+        // Cipher suites in GCM mode, see RFC 5288/5289.
+        //
+        // We may increase the priority of cipher suites in GCM mode when
+        // GCM technologies become mature in the industry.
+
+        // Suite B compliant cipher suites, see RFC 6460.
+        //
+        // Note that, at present this provider is not Suite B compliant. The
+        // preference order of the GCM cipher suites does not follow the spec
+        // of RFC 6460.
+        add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+            0xc02c, --p, K_ECDHE_ECDSA, B_AES_256_GCM, T, max, tls12, P_SHA384);
+        add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+            0xc02b, --p, K_ECDHE_ECDSA, B_AES_128_GCM, T, max, tls12, P_SHA256);
+
+        // AES_256(GCM)
+        add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+            0xc030, --p, K_ECDHE_RSA,   B_AES_256_GCM, T, max, tls12, P_SHA384);
+        add("TLS_RSA_WITH_AES_256_GCM_SHA384",
+            0x009d, --p, K_RSA,         B_AES_256_GCM, T, max, tls12, P_SHA384);
+        add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+            0xc02e, --p, K_ECDH_ECDSA,  B_AES_256_GCM, T, max, tls12, P_SHA384);
+        add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+            0xc032, --p, K_ECDH_RSA,    B_AES_256_GCM, T, max, tls12, P_SHA384);
+        add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+            0x009f, --p, K_DHE_RSA,     B_AES_256_GCM, T, max, tls12, P_SHA384);
+        add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
+            0x00a3, --p, K_DHE_DSS,     B_AES_256_GCM, T, max, tls12, P_SHA384);
+
+        // AES_128(GCM)
+        add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+            0xc02f, --p, K_ECDHE_RSA,   B_AES_128_GCM, T, max, tls12, P_SHA256);
+        add("TLS_RSA_WITH_AES_128_GCM_SHA256",
+            0x009c, --p, K_RSA,         B_AES_128_GCM, T, max, tls12, P_SHA256);
+        add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+            0xc02d, --p, K_ECDH_ECDSA,  B_AES_128_GCM, T, max, tls12, P_SHA256);
+        add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+            0xc031, --p, K_ECDH_RSA,    B_AES_128_GCM, T, max, tls12, P_SHA256);
+        add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+            0x009e, --p, K_DHE_RSA,     B_AES_128_GCM, T, max, tls12, P_SHA256);
+        add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+            0x00a2, --p, K_DHE_DSS,     B_AES_128_GCM, T, max, tls12, P_SHA256);
+        // End of cipher suites in GCM mode.
+
+        // 3DES_EDE
         add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
             0xC008, --p, K_ECDHE_ECDSA, B_3DES,    T);
         add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
@@ -1033,17 +1155,22 @@
          */
         p = DEFAULT_SUITES_PRIORITY;
 
+        add("TLS_DH_anon_WITH_AES_256_GCM_SHA384",
+            0x00a7, --p, K_DH_ANON,     B_AES_256_GCM, N, max, tls12, P_SHA384);
+        add("TLS_DH_anon_WITH_AES_128_GCM_SHA256",
+            0x00a6, --p, K_DH_ANON,     B_AES_128_GCM, N, max, tls12, P_SHA256);
+
         add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
             0x006d, --p, K_DH_ANON,     B_AES_256, N, max, tls12, P_SHA256);
         add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
-            0xC019, --p, K_ECDH_ANON,   B_AES_256, T);
+            0xC019, --p, K_ECDH_ANON,   B_AES_256, N);
         add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
             0x003a, --p, K_DH_ANON,     B_AES_256, N);
 
         add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
             0x006c, --p, K_DH_ANON,     B_AES_128, N, max, tls12, P_SHA256);
         add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
-            0xC018, --p, K_ECDH_ANON,   B_AES_128, T);
+            0xC018, --p, K_ECDH_ANON,   B_AES_128, N);
         add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
             0x0034, --p, K_DH_ANON,     B_AES_128, N);
 
@@ -1053,7 +1180,7 @@
             0x0018, --p, K_DH_ANON,     B_RC4_128, N);
 
         add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
-            0xC017, --p, K_ECDH_ANON,   B_3DES,    T);
+            0xC017, --p, K_ECDH_ANON,   B_3DES,    N);
         add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
             0x001b, --p, K_DH_ANON,     B_3DES,    N);
 
@@ -1208,18 +1335,10 @@
         add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256",          0x0069);
 
         // Unsupported cipher suites from RFC 5288
-        add("TLS_RSA_WITH_AES_128_GCM_SHA256",             0x009c);
-        add("TLS_RSA_WITH_AES_256_GCM_SHA384",             0x009d);
-        add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",         0x009e);
-        add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",         0x009f);
         add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256",          0x00a0);
         add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384",          0x00a1);
-        add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",         0x00a2);
-        add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",         0x00a3);
         add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256",          0x00a4);
         add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384",          0x00a5);
-        add("TLS_DH_anon_WITH_AES_128_GCM_SHA256",         0x00a6);
-        add("TLS_DH_anon_WITH_AES_256_GCM_SHA384",         0x00a7);
 
         // Unsupported cipher suites from RFC 5487
         add("TLS_PSK_WITH_AES_128_GCM_SHA256",             0x00a8);
@@ -1278,16 +1397,6 @@
         add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",        0xc021);
         add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",        0xc022);
 
-        // Unsupported cipher suites from RFC 5289
-        add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",     0xc02b);
-        add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",     0xc02c);
-        add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",      0xc02d);
-        add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",      0xc02e);
-        add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",       0xc02f);
-        add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",       0xc030);
-        add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",        0xc031);
-        add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",        0xc032);
-
         // Unsupported cipher suites from RFC 5489
         add("TLS_ECDHE_PSK_WITH_RC4_128_SHA",              0xc033);
         add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",         0xc034);
--- a/src/share/classes/sun/security/ssl/EngineInputRecord.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/EngineInputRecord.java	Tue Apr 16 05:11:50 2013 -0700
@@ -186,29 +186,35 @@
      * If external data(app), return a new ByteBuffer with data to
      * process.
      */
-    ByteBuffer decrypt(MAC signer,
+    ByteBuffer decrypt(Authenticator authenticator,
             CipherBox box, ByteBuffer bb) throws BadPaddingException {
 
         if (internalData) {
-            decrypt(signer, box);   // MAC is checked during decryption
+            decrypt(authenticator, box);   // MAC is checked during decryption
             return tmpBB;
         }
 
         BadPaddingException reservedBPE = null;
-        int tagLen = signer.MAClen();
+        int tagLen =
+            (authenticator instanceof MAC) ? ((MAC)authenticator).MAClen() : 0;
         int cipheredLength = bb.remaining();
 
         if (!box.isNullCipher()) {
-            // sanity check length of the ciphertext
-            if (!box.sanityCheck(tagLen, cipheredLength)) {
-                throw new BadPaddingException(
-                    "ciphertext sanity check failed");
-            }
+            try {
+                // apply explicit nonce for AEAD/CBC cipher suites if needed
+                int nonceSize =
+                    box.applyExplicitNonce(authenticator, contentType(), bb);
 
-            try {
+                // decrypt the content
+                if (box.isAEADMode()) {
+                    // DON'T encrypt the nonce_explicit for AEAD mode
+                    bb.position(bb.position() + nonceSize);
+                }   // The explicit IV for CBC mode can be decrypted.
+
                 // Note that the CipherBox.decrypt() does not change
                 // the capacity of the buffer.
                 box.decrypt(bb, tagLen);
+                bb.position(nonceSize); // We don't actually remove the nonce.
             } catch (BadPaddingException bpe) {
                 // RFC 2246 states that decryption_failed should be used
                 // for this purpose. However, that allows certain attacks,
@@ -219,12 +225,13 @@
                 //
                 // Failover to message authentication code checking.
                 reservedBPE = bpe;
-            } finally {
-                bb.rewind();
             }
         }
 
-        if (tagLen != 0) {
+        // Requires message authentication code for null, stream and block
+        // cipher suites.
+        if ((authenticator instanceof MAC) && (tagLen != 0)) {
+            MAC signer = (MAC)authenticator;
             int macOffset = bb.limit() - tagLen;
 
             // Note that although it is not necessary, we run the same MAC
@@ -297,6 +304,7 @@
     private static boolean checkMacTags(byte contentType, ByteBuffer bb,
             MAC signer, boolean isSimulated) {
 
+        int position = bb.position();
         int tagLen = signer.MAClen();
         int lim = bb.limit();
         int macData = lim - tagLen;
@@ -314,7 +322,8 @@
             int[] results = compareMacTags(bb, hash);
             return (results[0] != 0);
         } finally {
-            bb.rewind();
+            // reset to the data
+            bb.position(position);
             bb.limit(macData);
         }
     }
@@ -416,8 +425,8 @@
         if (debug != null && Debug.isOn("packet")) {
             try {
                 HexDumpEncoder hd = new HexDumpEncoder();
-                srcBB.limit(srcPos + len);
                 ByteBuffer bb = srcBB.duplicate();  // Use copy of BB
+                bb.limit(srcPos + len);
 
                 System.out.println("[Raw read (bb)]: length = " + len);
                 hd.encodeBuffer(bb, System.out);
--- a/src/share/classes/sun/security/ssl/EngineOutputRecord.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/EngineOutputRecord.java	Tue Apr 16 05:11:50 2013 -0700
@@ -29,7 +29,6 @@
 import java.io.*;
 import java.nio.*;
 
-
 /**
  * A OutputRecord class extension which uses external ByteBuffers
  * or the internal ByteArrayOutputStream for data manipulations.
@@ -101,51 +100,6 @@
         return finishedMsg;
     }
 
-
-    /**
-     * Calculate the MAC value, storing the result either in
-     * the internal buffer, or at the end of the destination
-     * ByteBuffer.
-     * <P>
-     * We assume that the higher levels have assured us enough
-     * room, otherwise we'll indirectly throw a
-     * BufferOverFlowException runtime exception.
-     *
-     * position should equal limit, and points to the next
-     * free spot.
-     */
-    private void addMAC(MAC signer, ByteBuffer bb)
-            throws IOException {
-
-        if (signer.MAClen() != 0) {
-            byte[] hash = signer.compute(contentType(), bb, false);
-
-            /*
-             * position was advanced to limit in compute above.
-             *
-             * Mark next area as writable (above layers should have
-             * established that we have plenty of room), then write
-             * out the hash.
-             */
-            bb.limit(bb.limit() + hash.length);
-            bb.put(hash);
-        }
-    }
-
-    /*
-     * Encrypt a ByteBuffer.
-     *
-     * We assume that the higher levels have assured us enough
-     * room for the encryption (plus padding), otherwise we'll
-     * indirectly throw a BufferOverFlowException runtime exception.
-     *
-     * position and limit will be the same, and points to the
-     * next free spot.
-     */
-    void encrypt(CipherBox box, ByteBuffer bb) {
-        box.encrypt(bb);
-    }
-
     /*
      * Override the actual write below.  We do things this way to be
      * consistent with InputRecord.  InputRecord may try to write out
@@ -160,7 +114,8 @@
          * Copy data out of buffer, it's ready to go.
          */
         ByteBuffer netBB = (ByteBuffer)
-            ByteBuffer.allocate(len).put(buf, 0, len).flip();
+            ByteBuffer.allocate(len).put(buf, off, len).flip();
+
         writer.putOutboundData(netBB);
     }
 
@@ -168,17 +123,19 @@
      * Main method for writing non-application data.
      * We MAC/encrypt, then send down for processing.
      */
-    void write(MAC writeMAC, CipherBox writeCipher) throws IOException {
+    void write(Authenticator authenticator, CipherBox writeCipher)
+            throws IOException {
+
         /*
          * Sanity check.
          */
         switch (contentType()) {
-        case ct_change_cipher_spec:
-        case ct_alert:
-        case ct_handshake:
-            break;
-        default:
-            throw new RuntimeException("unexpected byte buffers");
+            case ct_change_cipher_spec:
+            case ct_alert:
+            case ct_handshake:
+                break;
+            default:
+                throw new RuntimeException("unexpected byte buffers");
         }
 
         /*
@@ -193,10 +150,10 @@
          */
         if (!isEmpty()) {
             // compress();              // eventually
-            addMAC(writeMAC);
-            encrypt(writeCipher);
-            write((OutputStream)null, false,  // send down for processing
-                (ByteArrayOutputStream)null);
+            encrypt(authenticator, writeCipher);
+
+            // send down for processing
+            write((OutputStream)null, false, (ByteArrayOutputStream)null);
         }
         return;
     }
@@ -204,8 +161,8 @@
     /**
      * Main wrap/write driver.
      */
-    void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher)
-            throws IOException {
+    void write(EngineArgs ea, Authenticator authenticator,
+            CipherBox writeCipher) throws IOException {
         /*
          * sanity check to make sure someone didn't inadvertantly
          * send us an impossible combination we don't know how
@@ -217,7 +174,7 @@
          * Have we set the MAC's yet?  If not, we're not ready
          * to process application data yet.
          */
-        if (writeMAC == MAC.NULL) {
+        if (authenticator == MAC.NULL) {
             return;
         }
 
@@ -255,7 +212,7 @@
          */
         int length;
         if (engine.needToSplitPayload(writeCipher, protocolVersion)) {
-            write(ea, writeMAC, writeCipher, 0x01);
+            write(ea, authenticator, writeCipher, 0x01);
             ea.resetLim();      // reset application data buffer limit
             length = Math.min(ea.getAppRemaining(),
                         maxDataSizeMinusOneByteRecord);
@@ -265,14 +222,14 @@
 
         // Don't bother to really write empty records.
         if (length > 0) {
-            write(ea, writeMAC, writeCipher, length);
+            write(ea, authenticator, writeCipher, length);
         }
 
         return;
     }
 
-    void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher,
-            int length) throws IOException {
+    void write(EngineArgs ea, Authenticator authenticator,
+            CipherBox writeCipher, int length) throws IOException {
         /*
          * Copy out existing buffer values.
          */
@@ -286,39 +243,76 @@
          * Don't need to worry about SSLv2 rewrites, if we're here,
          * that's long since done.
          */
-        int dstData = dstPos + headerSize;
+        int dstData = dstPos + headerSize + writeCipher.getExplicitNonceSize();
         dstBB.position(dstData);
 
+        /*
+         * transfer application data into the network data buffer
+         */
         ea.gather(length);
+        dstBB.limit(dstBB.position());
+        dstBB.position(dstData);
 
         /*
          * "flip" but skip over header again, add MAC & encrypt
-         * addMAC will expand the limit to reflect the new
-         * data.
          */
-        dstBB.limit(dstBB.position());
-        dstBB.position(dstData);
-        addMAC(writeMAC, dstBB);
+        if (authenticator instanceof MAC) {
+            MAC signer = (MAC)authenticator;
+            if (signer.MAClen() != 0) {
+                byte[] hash = signer.compute(contentType(), dstBB, false);
+
+                /*
+                 * position was advanced to limit in compute above.
+                 *
+                 * Mark next area as writable (above layers should have
+                 * established that we have plenty of room), then write
+                 * out the hash.
+                 */
+                dstBB.limit(dstBB.limit() + hash.length);
+                dstBB.put(hash);
+
+                // reset the position and limit
+                dstBB.limit(dstBB.position());
+                dstBB.position(dstData);
+            }
+        }
 
-        /*
-         * Encrypt may pad, so again the limit may have changed.
-         */
-        dstBB.limit(dstBB.position());
-        dstBB.position(dstData);
-        encrypt(writeCipher, dstBB);
+        if (!writeCipher.isNullCipher()) {
+            /*
+             * Requires explicit IV/nonce for CBC/AEAD cipher suites for TLS 1.1
+             * or later.
+             */
+            if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
+                    (writeCipher.isCBCMode() || writeCipher.isAEADMode())) {
+                byte[] nonce = writeCipher.createExplicitNonce(
+                        authenticator, contentType(), dstBB.remaining());
+                dstBB.position(dstPos + headerSize);
+                dstBB.put(nonce);
+                if (!writeCipher.isAEADMode()) {
+                    // The explicit IV in TLS 1.1 and later can be encrypted.
+                    dstBB.position(dstPos + headerSize);
+                }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
+            }
 
-        if (debug != null
-                && (Debug.isOn("record") || Debug.isOn("handshake"))) {
-            if ((debug != null && Debug.isOn("record"))
-                    || contentType() == ct_change_cipher_spec)
+            /*
+             * Encrypt may pad, so again the limit may have changed.
+             */
+            writeCipher.encrypt(dstBB, dstLim);
+
+            if ((debug != null) && (Debug.isOn("record") ||
+                    (Debug.isOn("handshake") &&
+                        (contentType() == ct_change_cipher_spec)))) {
                 System.out.println(Thread.currentThread().getName()
                     // v3.0/v3.1 ...
                     + ", WRITE: " + protocolVersion
                     + " " + InputRecord.contentName(contentType())
                     + ", length = " + length);
+            }
+        } else {
+            dstBB.position(dstBB.limit());
         }
 
-        int packetLength = dstBB.limit() - dstData;
+        int packetLength = dstBB.limit() - dstPos - headerSize;
 
         /*
          * Finish out the record header.
@@ -333,7 +327,5 @@
          * Position was already set by encrypt() above.
          */
         dstBB.limit(dstLim);
-
-        return;
     }
 }
--- a/src/share/classes/sun/security/ssl/EngineWriter.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/EngineWriter.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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
@@ -99,7 +99,8 @@
      * other writeRecord.
      */
     synchronized void writeRecord(EngineOutputRecord outputRecord,
-            MAC writeMAC, CipherBox writeCipher) throws IOException {
+            Authenticator authenticator,
+            CipherBox writeCipher) throws IOException {
 
         /*
          * Only output if we're still open.
@@ -108,7 +109,7 @@
             throw new IOException("writer side was already closed.");
         }
 
-        outputRecord.write(writeMAC, writeCipher);
+        outputRecord.write(authenticator, writeCipher);
 
         /*
          * Did our handshakers notify that we just sent the
@@ -151,7 +152,8 @@
      * Return any determined status.
      */
     synchronized HandshakeStatus writeRecord(
-            EngineOutputRecord outputRecord, EngineArgs ea, MAC writeMAC,
+            EngineOutputRecord outputRecord, EngineArgs ea,
+            Authenticator authenticator,
             CipherBox writeCipher) throws IOException {
 
         /*
@@ -181,7 +183,7 @@
             throw new IOException("The write side was already closed");
         }
 
-        outputRecord.write(ea, writeMAC, writeCipher);
+        outputRecord.write(ea, authenticator, writeCipher);
 
         if (debug != null && Debug.isOn("packet")) {
             dumpPacket(ea, false);
--- a/src/share/classes/sun/security/ssl/Handshaker.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/Handshaker.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, 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
@@ -49,6 +49,7 @@
 import sun.security.ssl.CipherSuite.*;
 
 import static sun.security.ssl.CipherSuite.PRF.*;
+import static sun.security.ssl.CipherSuite.CipherType.*;
 
 /**
  * Handshaker ... processes handshake records from an SSL V3.0
@@ -714,33 +715,47 @@
     /**
      * Create a new read MAC and return it to caller.
      */
-    MAC newReadMAC() throws NoSuchAlgorithmException, InvalidKeyException {
-        MacAlg macAlg = cipherSuite.macAlg;
-        MAC mac;
-        if (isClient) {
-            mac = macAlg.newMac(protocolVersion, svrMacSecret);
-            svrMacSecret = null;
+    Authenticator newReadAuthenticator()
+            throws NoSuchAlgorithmException, InvalidKeyException {
+
+        Authenticator authenticator = null;
+        if (cipherSuite.cipher.cipherType == AEAD_CIPHER) {
+            authenticator = new Authenticator(protocolVersion);
         } else {
-            mac = macAlg.newMac(protocolVersion, clntMacSecret);
-            clntMacSecret = null;
+            MacAlg macAlg = cipherSuite.macAlg;
+            if (isClient) {
+                authenticator = macAlg.newMac(protocolVersion, svrMacSecret);
+                svrMacSecret = null;
+            } else {
+                authenticator = macAlg.newMac(protocolVersion, clntMacSecret);
+                clntMacSecret = null;
+            }
         }
-        return mac;
+
+        return authenticator;
     }
 
     /**
      * Create a new write MAC and return it to caller.
      */
-    MAC newWriteMAC() throws NoSuchAlgorithmException, InvalidKeyException {
-        MacAlg macAlg = cipherSuite.macAlg;
-        MAC mac;
-        if (isClient) {
-            mac = macAlg.newMac(protocolVersion, clntMacSecret);
-            clntMacSecret = null;
+    Authenticator newWriteAuthenticator()
+            throws NoSuchAlgorithmException, InvalidKeyException {
+
+        Authenticator authenticator = null;
+        if (cipherSuite.cipher.cipherType == AEAD_CIPHER) {
+            authenticator = new Authenticator(protocolVersion);
         } else {
-            mac = macAlg.newMac(protocolVersion, svrMacSecret);
-            svrMacSecret = null;
+            MacAlg macAlg = cipherSuite.macAlg;
+            if (isClient) {
+                authenticator = macAlg.newMac(protocolVersion, clntMacSecret);
+                clntMacSecret = null;
+            } else {
+                authenticator = macAlg.newMac(protocolVersion, svrMacSecret);
+                svrMacSecret = null;
+            }
         }
-        return mac;
+
+        return authenticator;
     }
 
     /*
@@ -1189,11 +1204,23 @@
         int prfHashLength = prf.getPRFHashLength();
         int prfBlockSize = prf.getPRFBlockSize();
 
+        // TLS v1.1 or later uses an explicit IV in CBC cipher suites to
+        // protect against the CBC attacks.  AEAD/GCM cipher suites in TLS
+        // v1.2 or later use a fixed IV as the implicit part of the partially
+        // implicit nonce technique described in RFC 5116.
+        int ivSize = cipher.ivSize;
+        if (cipher.cipherType == AEAD_CIPHER) {
+            ivSize = cipher.fixedIvSize;
+        } else if (protocolVersion.v >= ProtocolVersion.TLS11.v &&
+                cipher.cipherType == BLOCK_CIPHER) {
+            ivSize = 0;
+        }
+
         TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
             masterKey, protocolVersion.major, protocolVersion.minor,
             clnt_random.random_bytes, svr_random.random_bytes,
             cipher.algorithm, cipher.keySize, expandedKeySize,
-            cipher.ivSize, hashSize,
+            ivSize, hashSize,
             prfHashAlg, prfHashLength, prfBlockSize);
 
         try {
@@ -1201,14 +1228,15 @@
             kg.init(spec);
             TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
 
+            // Return null if cipher keys are not supposed to be generated.
             clntWriteKey = keySpec.getClientCipherKey();
             svrWriteKey = keySpec.getServerCipherKey();
 
             // Return null if IVs are not supposed to be generated.
-            // e.g. TLS 1.1+.
             clntWriteIV = keySpec.getClientIv();
             svrWriteIV = keySpec.getServerIv();
 
+            // Return null if MAC keys are not supposed to be generated.
             clntMacSecret = keySpec.getClientMacKey();
             svrMacSecret = keySpec.getServerMacKey();
         } catch (GeneralSecurityException e) {
@@ -1233,10 +1261,14 @@
                 printHex(dump, masterKey.getEncoded());
 
                 // Outputs:
-                System.out.println("Client MAC write Secret:");
-                printHex(dump, clntMacSecret.getEncoded());
-                System.out.println("Server MAC write Secret:");
-                printHex(dump, svrMacSecret.getEncoded());
+                if (clntMacSecret != null) {
+                    System.out.println("Client MAC write Secret:");
+                    printHex(dump, clntMacSecret.getEncoded());
+                    System.out.println("Server MAC write Secret:");
+                    printHex(dump, svrMacSecret.getEncoded());
+                } else {
+                    System.out.println("... no MAC keys used for this cipher");
+                }
 
                 if (clntWriteKey != null) {
                     System.out.println("Client write key:");
--- a/src/share/classes/sun/security/ssl/InputRecord.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/InputRecord.java	Tue Apr 16 05:11:50 2013 -0700
@@ -77,6 +77,17 @@
     /*
      * Construct the record to hold the maximum sized input record.
      * Data will be filled in separately.
+     *
+     * The structure of the byte buffer looks like:
+     *
+     *     |--------+---------+---------------------------------|
+     *     | header |   IV    | content, MAC/TAG, padding, etc. |
+     *     | headerPlusIVSize |
+     *
+     * header: the header of an SSL records
+     * IV:     the optional IV/nonce field, it is only required for block
+     *         (TLS 1.1 or later) and AEAD cipher suites.
+     *
      */
     InputRecord() {
         super(new byte[maxRecordSize]);
@@ -133,24 +144,34 @@
         return handshakeHash;
     }
 
-    void decrypt(MAC signer, CipherBox box) throws BadPaddingException {
-
+    void decrypt(Authenticator authenticator,
+            CipherBox box) throws BadPaddingException {
         BadPaddingException reservedBPE = null;
-        int tagLen = signer.MAClen();
+        int tagLen =
+            (authenticator instanceof MAC) ? ((MAC)authenticator).MAClen() : 0;
         int cipheredLength = count - headerSize;
 
         if (!box.isNullCipher()) {
-            // sanity check length of the ciphertext
-            if (!box.sanityCheck(tagLen, cipheredLength)) {
-                throw new BadPaddingException(
-                    "ciphertext sanity check failed");
-            }
+            try {
+                // apply explicit nonce for AEAD/CBC cipher suites if needed
+                int nonceSize = box.applyExplicitNonce(authenticator,
+                        contentType(), buf, headerSize, cipheredLength);
+                pos = headerSize + nonceSize;
+                lastHashed = pos;   // don't digest the explicit nonce
 
-            try {
+                // decrypt the content
+                int offset = headerSize;
+                if (box.isAEADMode()) {
+                    // DON'T encrypt the nonce_explicit for AEAD mode
+                    offset += nonceSize;
+                }   // The explicit IV for CBC mode can be decrypted.
+
                 // Note that the CipherBox.decrypt() does not change
                 // the capacity of the buffer.
-                count = headerSize +
-                        box.decrypt(buf, headerSize, cipheredLength, tagLen);
+                count = offset +
+                    box.decrypt(buf, offset, count - offset, tagLen);
+
+                // Note that we don't remove the nonce from the buffer.
             } catch (BadPaddingException bpe) {
                 // RFC 2246 states that decryption_failed should be used
                 // for this purpose. However, that allows certain attacks,
@@ -164,9 +185,12 @@
             }
         }
 
-        if (tagLen != 0) {
+        // Requires message authentication code for null, stream and block
+        // cipher suites.
+        if (authenticator instanceof MAC && tagLen != 0) {
+            MAC signer = (MAC)authenticator;
             int macOffset = count - tagLen;
-            int contentLen = macOffset - headerSize;
+            int contentLen = macOffset - pos;
 
             // Note that although it is not necessary, we run the same MAC
             // computation and comparison on the payload for both stream
@@ -190,7 +214,7 @@
 
             // Run MAC computation and comparison on the payload.
             if (checkMacTags(contentType(),
-                    buf, headerSize, contentLen, signer, false)) {
+                    buf, pos, contentLen, signer, false)) {
                 if (reservedBPE == null) {
                     reservedBPE = new BadPaddingException("bad record MAC");
                 }
--- a/src/share/classes/sun/security/ssl/JsseJce.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/JsseJce.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, 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
@@ -155,6 +155,11 @@
      */
     final static String CIPHER_AES = "AES/CBC/NoPadding";
     /**
+     * JCE transformation string for AES in GCM mode
+     * without padding.
+     */
+    final static String CIPHER_AES_GCM = "AES/GCM/NoPadding";
+    /**
      * JCA identifier string for DSA, i.e. a DSA with SHA-1.
      */
     final static String SIGNATURE_DSA = "DSA";
--- a/src/share/classes/sun/security/ssl/MAC.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/MAC.java	Tue Apr 16 05:11:50 2013 -0700
@@ -39,19 +39,15 @@
 
 /**
  * This class computes the "Message Authentication Code" (MAC) for each
- * SSL message.  This is essentially a shared-secret signature, used to
- * provide integrity protection for SSL messages.  The MAC is actually
- * one of several keyed hashes, as associated with the cipher suite and
- * protocol version.  (SSL v3.0 uses one construct, TLS uses another.)
- * <P>
- * NOTE: MAC computation is the only place in the SSL protocol that the
- * sequence number is used.  It's also reset to zero with each change of
- * a cipher spec, so this is the only place this state is needed.
+ * SSL stream and block cipher message.  This is essentially a shared-secret
+ * signature, used to provide integrity protection for SSL messages.  The
+ * MAC is actually one of several keyed hashes, as associated with the cipher
+ * suite and protocol version. (SSL v3.0 uses one construct, TLS uses another.)
  *
  * @author David Brownell
  * @author Andreas Sterbenz
  */
-final class MAC {
+final class MAC extends Authenticator {
 
     final static MAC NULL = new MAC();
 
@@ -61,33 +57,12 @@
     // internal identifier for the MAC algorithm
     private final MacAlg        macAlg;
 
-    // stuff defined by the kind of MAC algorithm
-    private final int           macSize;
-
     // JCE Mac object
     private final Mac mac;
 
-    // byte array containing the additional information we MAC in each record
-    // (see below)
-    private final byte[] block;
-
-    // sequence number + record type + + record length
-    private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
-
-    // sequence number + record type + protocol version + record length
-    private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
-
-    // offset of record type in block
-    private static final int BLOCK_OFFSET_TYPE    = 8;
-
-    // offset of protocol version number in block (TLS only)
-    private static final int BLOCK_OFFSET_VERSION = 8 + 1;
-
     private MAC() {
-        macSize = 0;
         macAlg = M_NULL;
         mac = null;
-        block = null;
     }
 
     /**
@@ -95,8 +70,8 @@
      */
     MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
             throws NoSuchAlgorithmException, InvalidKeyException {
+        super(protocolVersion);
         this.macAlg = macAlg;
-        this.macSize = macAlg.size;
 
         String algorithm;
         boolean tls = (protocolVersion.v >= ProtocolVersion.TLS10.v);
@@ -115,21 +90,13 @@
 
         mac = JsseJce.getMac(algorithm);
         mac.init(key);
-
-        if (tls) {
-            block = new byte[BLOCK_SIZE_TLS];
-            block[BLOCK_OFFSET_VERSION]   = protocolVersion.major;
-            block[BLOCK_OFFSET_VERSION+1] = protocolVersion.minor;
-        } else {
-            block = new byte[BLOCK_SIZE_SSL];
-        }
     }
 
     /**
      * Returns the length of the MAC.
      */
     int MAClen() {
-        return macSize;
+        return macAlg.size;
     }
 
     /**
@@ -157,7 +124,17 @@
      */
     final byte[] compute(byte type, byte buf[],
             int offset, int len, boolean isSimulated) {
-        return compute(type, null, buf, offset, len, isSimulated);
+        if (macAlg.size == 0) {
+            return nullMAC;
+        }
+
+        if (!isSimulated) {
+            byte[] additional = acquireAuthenticationBytes(type, len);
+            mac.update(additional);
+        }
+        mac.update(buf, offset, len);
+
+        return mac.doFinal();
     }
 
     /**
@@ -173,83 +150,19 @@
      * @param isSimulated if true, simulate the the MAC computation
      */
     final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) {
-        return compute(type, bb, null, 0, bb.remaining(), isSimulated);
-    }
-
-    /**
-     * Check whether the sequence number is close to wrap
-     *
-     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
-     * Sequence numbers do not wrap. When the sequence number is near
-     * to wrap, we need to close the connection immediately.
-     */
-    final boolean seqNumOverflow() {
-        /*
-         * Conservatively, we don't allow more records to be generated
-         * when there are only 2^8 sequence numbers left.
-         */
-        return (block != null && mac != null &&
-                block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
-                block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
-                block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
-                block[6] == (byte)0xFF);
-    }
-
-    /*
-     * Check whether to renew the sequence number
-     *
-     * Sequence numbers are of type uint64 and may not exceed 2^64-1.
-     * Sequence numbers do not wrap.  If a TLS
-     * implementation would need to wrap a sequence number, it must
-     * renegotiate instead.
-     */
-    final boolean seqNumIsHuge() {
-        /*
-         * Conservatively, we should ask for renegotiation when there are
-         * only 2^48 sequence numbers left.
-         */
-        return (block != null && mac != null &&
-                block[0] == (byte)0xFF && block[1] == (byte)0xFF);
-    }
-
-    // increment the sequence number in the block array
-    // it is a 64-bit number stored in big-endian format
-    private void incrementSequenceNumber() {
-        int k = 7;
-        while ((k >= 0) && (++block[k] == 0)) {
-            k--;
-        }
-    }
-
-    /*
-     * Compute based on either buffer type, either bb.position/limit
-     * or buf/offset/len.
-     */
-    private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
-            int offset, int len, boolean isSimulated) {
-
-        if (macSize == 0) {
+        if (macAlg.size == 0) {
             return nullMAC;
         }
 
-        // MUST NOT increase the sequence number for a simulated computation.
         if (!isSimulated) {
-            block[BLOCK_OFFSET_TYPE] = type;
-            block[block.length - 2]  = (byte)(len >> 8);
-            block[block.length - 1]  = (byte)(len     );
-
-            mac.update(block);
-            incrementSequenceNumber();
+            byte[] additional =
+                    acquireAuthenticationBytes(type, bb.remaining());
+            mac.update(additional);
         }
-
-        // content
-        if (bb != null) {
-            mac.update(bb);
-        } else {
-            mac.update(buf, offset, len);
-        }
+        mac.update(bb);
 
         return mac.doFinal();
     }
 
 }
+
--- a/src/share/classes/sun/security/ssl/OutputRecord.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/OutputRecord.java	Tue Apr 16 05:11:50 2013 -0700
@@ -54,6 +54,7 @@
     private int                 lastHashed;
     private boolean             firstMessage;
     final private byte          contentType;
+    private int                 headerOffset;
 
     // current protocol version, sent as record version
     ProtocolVersion     protocolVersion;
@@ -70,6 +71,23 @@
      * Default constructor makes a record supporting the maximum
      * SSL record size.  It allocates the header bytes directly.
      *
+     * The structure of the byte buffer looks like:
+     *
+     *     |---------+--------+-------+---------------------------------|
+     *     | unused  | header |  IV   | content, MAC/TAG, padding, etc. |
+     *     |    headerPlusMaxIVSize   |
+     *
+     * unused: unused part of the buffer of size
+     *
+     *             headerPlusMaxIVSize - header size - IV size
+     *
+     *         When this object is created, we don't know the protocol
+     *         version number, IV length, etc., so reserve space in front
+     *         to avoid extra data movement (copies).
+     * header: the header of an SSL record
+     * IV:     the optional IV/nonce field, it is only required for block
+     *         (TLS 1.1 or later) and AEAD cipher suites.
+     *
      * @param type the content type for the record
      */
     OutputRecord(byte type, int size) {
@@ -77,9 +95,10 @@
         this.protocolVersion = ProtocolVersion.DEFAULT;
         this.helloVersion = ProtocolVersion.DEFAULT_HELLO;
         firstMessage = true;
-        count = headerSize;
+        count = headerPlusMaxIVSize;
         contentType = type;
         lastHashed = count;
+        headerOffset = headerPlusMaxIVSize - headerSize;
     }
 
     OutputRecord(byte type) {
@@ -119,8 +138,9 @@
     @Override
     public synchronized void reset() {
         super.reset();
-        count = headerSize;
+        count = headerPlusMaxIVSize;
         lastHashed = count;
+        headerOffset = headerPlusMaxIVSize - headerSize;
     }
 
     /*
@@ -173,58 +193,84 @@
      * of sending empty records over the network.
      */
     boolean isEmpty() {
-        return count == headerSize;
+        return count == headerPlusMaxIVSize;
     }
 
     /*
-     * Return true if the record is of a given alert.
+     * Return true if the record is of an alert of the given description.
+     *
+     * Per SSL/TLS specifications, alert messages convey the severity of the
+     * message (warning or fatal) and a description of the alert. An alert
+     * is defined with a two bytes struct, {byte level, byte description},
+     * following after the header bytes.
      */
     boolean isAlert(byte description) {
-        // An alert is defined with a two bytes struct,
-        // {byte level, byte description}, following after the header bytes.
-        if (count > (headerSize + 1) && contentType == ct_alert) {
-            return buf[headerSize + 1] == description;
+        if ((count > (headerPlusMaxIVSize + 1)) && (contentType == ct_alert)) {
+            return buf[headerPlusMaxIVSize + 1] == description;
         }
 
         return false;
     }
 
     /*
-     * Compute the MAC and append it to this record.  In case we
-     * are automatically flushing a handshake stream, make sure we
-     * have hashed the message first.
+     * Encrypt ... length may grow due to block cipher padding, or
+     * message authentication code or tag.
      */
-    void addMAC(MAC signer) throws IOException {
+    void encrypt(Authenticator authenticator, CipherBox box)
+            throws IOException {
+
+        // In case we are automatically flushing a handshake stream, make
+        // sure we have hashed the message first.
         //
         // when we support compression, hashing can't go here
         // since it'll need to be done on the uncompressed data,
         // and the MAC applies to the compressed data.
-        //
         if (contentType == ct_handshake) {
             doHashes();
         }
-        if (signer.MAClen() != 0) {
-            byte[] hash = signer.compute(contentType, buf,
-                    headerSize, count - headerSize, false);
-            write(hash);
+
+        // Requires message authentication code for stream and block
+        // cipher suites.
+        if (authenticator instanceof MAC) {
+            MAC signer = (MAC)authenticator;
+            if (signer.MAClen() != 0) {
+                byte[] hash = signer.compute(contentType, buf,
+                    headerPlusMaxIVSize, count - headerPlusMaxIVSize, false);
+                write(hash);
+            }
+        }
+
+        if (!box.isNullCipher()) {
+            // Requires explicit IV/nonce for CBC/AEAD cipher suites for
+            // TLS 1.1 or later.
+            if ((protocolVersion.v >= ProtocolVersion.TLS11.v) &&
+                                    (box.isCBCMode() || box.isAEADMode())) {
+                byte[] nonce = box.createExplicitNonce(authenticator,
+                                    contentType, count - headerPlusMaxIVSize);
+                int offset = headerPlusMaxIVSize - nonce.length;
+                System.arraycopy(nonce, 0, buf, offset, nonce.length);
+                headerOffset = offset - headerSize;
+            } else {
+                headerOffset = headerPlusMaxIVSize - headerSize;
+            }
+
+            // encrypt the content
+            int offset = headerPlusMaxIVSize;
+            if (!box.isAEADMode()) {
+                // The explicit IV can be encrypted.
+                offset = headerOffset + headerSize;
+            }   // Otherwise, DON'T encrypt the nonce_explicit for AEAD mode
+
+            count = offset + box.encrypt(buf, offset, count - offset);
         }
     }
 
     /*
-     * Encrypt ... length may grow due to block cipher padding
-     */
-    void encrypt(CipherBox box) {
-        int len = count - headerSize;
-        count = headerSize + box.encrypt(buf, headerSize, len);
-    }
-
-
-    /*
      * Tell how full the buffer is ... for filling it with application or
      * handshake data.
      */
     final int availableDataBytes() {
-        int dataSize = count - headerSize;
+        int dataSize = count - headerPlusMaxIVSize;
         return maxDataSize - dataSize;
     }
 
@@ -270,11 +316,11 @@
          * Don't emit content-free records.  (Even change cipher spec
          * messages have a byte of data!)
          */
-        if (count == headerSize) {
+        if (count == headerPlusMaxIVSize) {
             return;
         }
 
-        int length = count - headerSize;
+        int length = count - headerOffset - headerSize;
         // "should" really never write more than about 14 Kb...
         if (length < 0) {
             throw new SSLException("output record size too small: "
@@ -299,7 +345,9 @@
          */
          if (firstMessage && useV2Hello()) {
             byte[] v3Msg = new byte[length - 4];
-            System.arraycopy(buf, headerSize + 4, v3Msg, 0, v3Msg.length);
+            System.arraycopy(buf, headerPlusMaxIVSize + 4,
+                                        v3Msg, 0, v3Msg.length);
+            headerOffset = 0;   // reset the header offset
             V3toV2ClientHello(v3Msg);
             handshakeHash.reset();
             lastHashed = 2;
@@ -314,11 +362,11 @@
             /*
              * Fill out the header, write it and the message.
              */
-            buf[0] = contentType;
-            buf[1] = protocolVersion.major;
-            buf[2] = protocolVersion.minor;
-            buf[3] = (byte)(length >> 8);
-            buf[4] = (byte)(length);
+            buf[headerOffset + 0] = contentType;
+            buf[headerOffset + 1] = protocolVersion.major;
+            buf[headerOffset + 2] = protocolVersion.minor;
+            buf[headerOffset + 3] = (byte)(length >> 8);
+            buf[headerOffset + 4] = (byte)(length);
         }
         firstMessage = false;
 
@@ -338,7 +386,8 @@
              * when holdRecord is true, the implementation in this class
              * will be used.
              */
-            writeBuffer(heldRecordBuffer, buf, 0, count, debugOffset);
+            writeBuffer(heldRecordBuffer,
+                        buf, headerOffset, count - headerOffset, debugOffset);
         } else {
             // It's time to send, do we have buffered data?
             // May or may not have a heldRecordBuffer.
@@ -346,15 +395,18 @@
                 int heldLen = heldRecordBuffer.size();
 
                 // Ensure the capacity of this buffer.
-                ensureCapacity(count + heldLen);
+                int newCount = count + heldLen - headerOffset;
+                ensureCapacity(newCount);
 
                 // Slide everything in the buffer to the right.
-                System.arraycopy(buf, 0, buf, heldLen, count);
+                System.arraycopy(buf, headerOffset,
+                                    buf, heldLen, count - headerOffset);
 
                 // Prepend the held record to the buffer.
                 System.arraycopy(
                     heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen);
-                count += heldLen;
+                count = newCount;
+                headerOffset = 0;
 
                 // Clear the held buffer.
                 heldRecordBuffer.reset();
@@ -362,7 +414,8 @@
                 // The held buffer has been dumped, set the debug dump offset.
                 debugOffset = heldLen;
             }
-            writeBuffer(s, buf, 0, count, debugOffset);
+            writeBuffer(s, buf, headerOffset,
+                        count - headerOffset, debugOffset);
         }
 
         reset();
@@ -382,12 +435,11 @@
         if (debug != null && Debug.isOn("packet")) {
             try {
                 HexDumpEncoder hd = new HexDumpEncoder();
-                ByteBuffer bb = ByteBuffer.wrap(
-                        buf, off + debugOffset, len - debugOffset);
 
                 System.out.println("[Raw write]: length = " +
-                    bb.remaining());
-                hd.encodeBuffer(bb, System.out);
+                                                    (len - debugOffset));
+                hd.encodeBuffer(new ByteArrayInputStream(buf,
+                    off + debugOffset, len - debugOffset), System.out);
             } catch (IOException e) { }
         }
     }
@@ -400,8 +452,13 @@
         return firstMessage
             && (helloVersion == ProtocolVersion.SSL20Hello)
             && (contentType == ct_handshake)
-            && (buf[5] == HandshakeMessage.ht_client_hello)
-            && (buf[headerSize + 4+2+32] == 0); // V3 session ID is empty
+            && (buf[headerOffset + 5] == HandshakeMessage.ht_client_hello)
+                                            //  5: recode header size
+            && (buf[headerPlusMaxIVSize + 4 + 2 + 32] == 0);
+                                            // V3 session ID is empty
+                                            //  4: handshake header size
+                                            //  2: client_version in ClientHello
+                                            // 32: random in ClientHello
     }
 
     /*
--- a/src/share/classes/sun/security/ssl/Record.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/Record.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, 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
@@ -52,20 +52,29 @@
     static final int    trailerSize = 20;       // SHA1 hash size
     static final int    maxDataSize = 16384;    // 2^14 bytes of data
     static final int    maxPadding = 256;       // block cipher padding
-    static final int    maxIVLength = 256;      // block length
+    static final int    maxIVLength = 256;      // IV length
+
+    /*
+     * The size of the header plus the max IV length
+     */
+    static final int    headerPlusMaxIVSize =
+                                      headerSize        // header
+                                    + maxIVLength;      // iv
 
     /*
      * SSL has a maximum record size.  It's header, (compressed) data,
-     * padding, and a trailer for the MAC.
+     * padding, and a trailer for the message authentication information (MAC
+     * for block and stream ciphers, and message authentication tag for AEAD
+     * ciphers).
+     *
      * Some compression algorithms have rare cases where they expand the data.
      * As we don't support compression at this time, leave that out.
      */
     static final int    maxRecordSize =
-                                      headerSize        // header
-                                    + maxIVLength       // iv
-                                    + maxDataSize       // data
-                                    + maxPadding        // padding
-                                    + trailerSize;      // MAC
+                                      headerPlusMaxIVSize   // header + iv
+                                    + maxDataSize           // data
+                                    + maxPadding            // padding
+                                    + trailerSize;          // MAC or AEAD tag
 
     static final boolean enableCBCProtection =
             Debug.getBooleanProperty("jsse.enableCBCProtection", true);
@@ -77,8 +86,7 @@
     static final int    maxDataSizeMinusOneByteRecord =
                                   maxDataSize       // max data size
                                 - (                 // max one byte record size
-                                      headerSize    // header
-                                    + maxIVLength   // iv
+                                      headerPlusMaxIVSize   // header + iv
                                     + 1             // one byte data
                                     + maxPadding    // padding
                                     + trailerSize   // MAC
@@ -104,11 +112,10 @@
      * Allocate a smaller array.
      */
     static final int    maxAlertRecordSize =
-                                      headerSize        // header
-                                    + maxIVLength       // iv
-                                    + 2                 // alert
-                                    + maxPadding        // padding
-                                    + trailerSize;      // MAC
+                                      headerPlusMaxIVSize   // header + iv
+                                    + 2                     // alert
+                                    + maxPadding            // padding
+                                    + trailerSize;          // MAC
 
     /*
      * The overflow values of integers of 8, 16 and 24 bits.
--- a/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/SSLEngineImpl.java	Tue Apr 16 05:11:50 2013 -0700
@@ -280,7 +280,7 @@
     /*
      * Crypto state that's reinitialized when the session changes.
      */
-    private MAC                 readMAC, writeMAC;
+    private Authenticator       readAuthenticator, writeAuthenticator;
     private CipherBox           readCipher, writeCipher;
     // NOTE: compression state would be saved here
 
@@ -377,9 +377,9 @@
          * Note:  compression support would go here too
          */
         readCipher = CipherBox.NULL;
-        readMAC = MAC.NULL;
+        readAuthenticator = MAC.NULL;
         writeCipher = CipherBox.NULL;
-        writeMAC = MAC.NULL;
+        writeAuthenticator = MAC.NULL;
 
         // default security parameters for secure renegotiation
         secureRenegotiation = false;
@@ -586,7 +586,7 @@
 
         try {
             readCipher = handshaker.newReadCipher();
-            readMAC = handshaker.newReadMAC();
+            readAuthenticator = handshaker.newReadAuthenticator();
         } catch (GeneralSecurityException e) {
             // "can't happen"
             throw new SSLException("Algorithm missing:  ", e);
@@ -622,7 +622,7 @@
 
         try {
             writeCipher = handshaker.newWriteCipher();
-            writeMAC = handshaker.newWriteMAC();
+            writeAuthenticator = handshaker.newWriteAuthenticator();
         } catch (GeneralSecurityException e) {
             // "can't happen"
             throw new SSLException("Algorithm missing:  ", e);
@@ -958,7 +958,8 @@
              * throw a fatal alert if the integrity check fails.
              */
             try {
-                decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB);
+                decryptedBB = inputRecord.decrypt(
+                                    readAuthenticator, readCipher, readBB);
             } catch (BadPaddingException e) {
                 byte alertType = (inputRecord.contentType() ==
                     Record.ct_handshake) ?
@@ -967,7 +968,6 @@
                 fatal(alertType, e.getMessage(), e);
             }
 
-
             // if (!inputRecord.decompress(c))
             //     fatal(Alerts.alert_decompression_failure,
             //     "decompression failure");
@@ -1117,7 +1117,7 @@
                 hsStatus = getHSStatus(hsStatus);
                 if (connectionState < cs_ERROR && !isInboundDone() &&
                         (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
-                    if (checkSequenceNumber(readMAC,
+                    if (checkSequenceNumber(readAuthenticator,
                             inputRecord.contentType())) {
                         hsStatus = getHSStatus(null);
                     }
@@ -1270,7 +1270,7 @@
 
         // eventually compress as well.
         HandshakeStatus hsStatus =
-                writer.writeRecord(eor, ea, writeMAC, writeCipher);
+                writer.writeRecord(eor, ea, writeAuthenticator, writeCipher);
 
         /*
          * We only need to check the sequence number state for
@@ -1287,7 +1287,7 @@
         hsStatus = getHSStatus(hsStatus);
         if (connectionState < cs_ERROR && !isOutboundDone() &&
                 (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
-            if (checkSequenceNumber(writeMAC, eor.contentType())) {
+            if (checkSequenceNumber(writeAuthenticator, eor.contentType())) {
                 hsStatus = getHSStatus(null);
             }
         }
@@ -1326,7 +1326,7 @@
      */
     void writeRecord(EngineOutputRecord eor) throws IOException {
         // eventually compress as well.
-        writer.writeRecord(eor, writeMAC, writeCipher);
+        writer.writeRecord(eor, writeAuthenticator, writeCipher);
 
         /*
          * Check the sequence number state
@@ -1340,7 +1340,7 @@
          * of the last record cannot be wrapped.
          */
         if ((connectionState < cs_ERROR) && !isOutboundDone()) {
-            checkSequenceNumber(writeMAC, eor.contentType());
+            checkSequenceNumber(writeAuthenticator, eor.contentType());
         }
     }
 
@@ -1358,14 +1358,14 @@
      *
      * Return true if the handshake status may be changed.
      */
-    private boolean checkSequenceNumber(MAC mac, byte type)
+    private boolean checkSequenceNumber(Authenticator authenticator, byte type)
             throws IOException {
 
         /*
          * Don't bother to check the sequence number for error or
          * closed connections, or NULL MAC
          */
-        if (connectionState >= cs_ERROR || mac == MAC.NULL) {
+        if (connectionState >= cs_ERROR || authenticator == MAC.NULL) {
             return false;
         }
 
@@ -1373,7 +1373,7 @@
          * Conservatively, close the connection immediately when the
          * sequence number is close to overflow
          */
-        if (mac.seqNumOverflow()) {
+        if (authenticator.seqNumOverflow()) {
             /*
              * TLS protocols do not define a error alert for sequence
              * number overflow. We use handshake_failure error alert
@@ -1396,7 +1396,7 @@
          * Don't bother to kickstart the renegotiation when the local is
          * asking for it.
          */
-        if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
+        if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) {
             if (debug != null && Debug.isOn("ssl")) {
                 System.out.println(Thread.currentThread().getName() +
                         ", request renegotiation " +
--- a/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/classes/sun/security/ssl/SSLSocketImpl.java	Tue Apr 16 05:11:50 2013 -0700
@@ -292,7 +292,7 @@
     /*
      * Crypto state that's reinitialized when the session changes.
      */
-    private MAC                 readMAC, writeMAC;
+    private Authenticator       readAuthenticator, writeAuthenticator;
     private CipherBox           readCipher, writeCipher;
     // NOTE: compression state would be saved here
 
@@ -586,9 +586,9 @@
          * Note:  compression support would go here too
          */
         readCipher = CipherBox.NULL;
-        readMAC = MAC.NULL;
+        readAuthenticator = MAC.NULL;
         writeCipher = CipherBox.NULL;
-        writeMAC = MAC.NULL;
+        writeAuthenticator = MAC.NULL;
 
         // initial security parameters for secure renegotiation
         secureRenegotiation = false;
@@ -829,8 +829,7 @@
             boolean holdRecord) throws IOException {
 
         // r.compress(c);
-        r.addMAC(writeMAC);
-        r.encrypt(writeCipher);
+        r.encrypt(writeAuthenticator, writeCipher);
 
         if (holdRecord) {
             // If we were requested to delay the record due to possibility
@@ -861,7 +860,7 @@
          * of the last record cannot be wrapped.
          */
         if (connectionState < cs_ERROR) {
-            checkSequenceNumber(writeMAC, r.contentType());
+            checkSequenceNumber(writeAuthenticator, r.contentType());
         }
 
         // turn off the flag of the first application record
@@ -986,7 +985,7 @@
              * throw a fatal alert if the integrity check fails.
              */
             try {
-                r.decrypt(readMAC, readCipher);
+                r.decrypt(readAuthenticator, readCipher);
             } catch (BadPaddingException e) {
                 byte alertType = (r.contentType() == Record.ct_handshake)
                                         ? Alerts.alert_handshake_failure
@@ -1143,7 +1142,7 @@
                * of the last record cannot be wrapped.
                */
               if (connectionState < cs_ERROR) {
-                  checkSequenceNumber(readMAC, r.contentType());
+                  checkSequenceNumber(readAuthenticator, r.contentType());
               }
 
               return;
@@ -1166,14 +1165,14 @@
      * implementation would need to wrap a sequence number, it must
      * renegotiate instead."
      */
-    private void checkSequenceNumber(MAC mac, byte type)
+    private void checkSequenceNumber(Authenticator authenticator, byte type)
             throws IOException {
 
         /*
          * Don't bother to check the sequence number for error or
          * closed connections, or NULL MAC.
          */
-        if (connectionState >= cs_ERROR || mac == MAC.NULL) {
+        if (connectionState >= cs_ERROR || authenticator == MAC.NULL) {
             return;
         }
 
@@ -1181,7 +1180,7 @@
          * Conservatively, close the connection immediately when the
          * sequence number is close to overflow
          */
-        if (mac.seqNumOverflow()) {
+        if (authenticator.seqNumOverflow()) {
             /*
              * TLS protocols do not define a error alert for sequence
              * number overflow. We use handshake_failure error alert
@@ -1203,7 +1202,7 @@
          * Don't bother to kickstart the renegotiation when the local is
          * asking for it.
          */
-        if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
+        if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) {
             if (debug != null && Debug.isOn("ssl")) {
                 System.out.println(Thread.currentThread().getName() +
                         ", request renegotiation " +
@@ -2065,7 +2064,7 @@
 
         try {
             readCipher = handshaker.newReadCipher();
-            readMAC = handshaker.newReadMAC();
+            readAuthenticator = handshaker.newReadAuthenticator();
         } catch (GeneralSecurityException e) {
             // "can't happen"
             throw new SSLException("Algorithm missing:  ", e);
@@ -2096,7 +2095,7 @@
 
         try {
             writeCipher = handshaker.newWriteCipher();
-            writeMAC = handshaker.newWriteMAC();
+            writeAuthenticator = handshaker.newWriteAuthenticator();
         } catch (GeneralSecurityException e) {
             // "can't happen"
             throw new SSLException("Algorithm missing:  ", e);
--- a/src/share/lib/security/java.security-linux	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/lib/security/java.security-linux	Tue Apr 16 05:11:50 2013 -0700
@@ -76,26 +76,57 @@
 security.provider.9=sun.security.smartcardio.SunPCSC
 
 #
-# Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by
-# the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity
-# algorithm is used.
+# Sun Provider SecureRandom seed source.
+#
+# Select the primary source of seed data for the "SHA1PRNG" and
+# "NativePRNG" SecureRandom implementations in the "Sun" provider.
+# (Other SecureRandom implementations might also use this property.)
+#
+# On Unix-like systems (for example, Solaris/Linux/MacOS), the
+# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from
+# special device files such as file:/dev/random.
 #
-# On Solaris and Linux systems, if file:/dev/urandom is specified and it
-# exists, a special SecureRandom implementation is activated by default.
-# This "NativePRNG" reads random bytes directly from /dev/urandom.
+# On Windows systems, specifying the URLs "file:/dev/random" or
+# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding
+# mechanism for SHA1PRNG.
+#
+# By default, an attempt is made to use the entropy gathering device
+# specified by the "securerandom.source" Security property.  If an
+# exception occurs while accessing the specified URL:
+#
+#     SHA1PRNG:
+#         the traditional system/thread activity algorithm will be used.
+#
+#     NativePRNG:
+#         a default value of /dev/random will be used.  If neither
+#         are available, the implementation will be disabled.
+#         "file" is the only currently supported protocol type.
 #
-# On Windows systems, the URLs file:/dev/random and file:/dev/urandom
-# enables use of the Microsoft CryptoAPI seed functionality.
+# The entropy gathering device can also be specified with the System
+# property "java.security.egd". For example:
+#
+#   % java -Djava.security.egd=file:/dev/random MainClass
 #
-securerandom.source=file:/dev/urandom
+# Specifying this System property will override the
+# "securerandom.source" Security property.
+#
+# In addition, if "file:/dev/random" or "file:/dev/urandom" is
+# specified, the "NativePRNG" implementation will be more preferred than
+# SHA1PRNG in the Sun provider.
 #
-# The entropy gathering device is described as a URL and can also
-# be specified with the system property "java.security.egd". For example,
-#   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source
-# setting.
+securerandom.source=file:/dev/random
+
+#
+# A list of known strong SecureRandom implementations.
+#
+# To help guide applications in selecting a suitable strong
+# java.security.SecureRandom implementation, Java distributions should
+# indicate a list of known strong implementations using the property.
+#
+# This is a comma-separated list of algorithm and/or algorithm:provider
+# entries.
+#
+securerandom.strongAlgorithms=NativePRNGBlocking:SUN
 
 #
 # Class to instantiate as the javax.security.auth.login.Configuration
@@ -159,9 +190,9 @@
                com.sun.org.glassfish.gmbal.,\
                com.oracle.xmlns.internal.,\
                com.oracle.webservices.internal.,\
-	       jdk.internal.,\
-	       jdk.nashorn.internal.,\
-	       jdk.nashorn.tools.
+               jdk.internal.,\
+               jdk.nashorn.internal.,\
+               jdk.nashorn.tools.
 
 #
 # List of comma-separated packages that start with or equal this string
@@ -187,9 +218,9 @@
                    com.sun.org.glassfish.gmbal.,\
                    com.oracle.xmlns.internal.,\
                    com.oracle.webservices.internal.,\
-		   jdk.internal.,\
-		   jdk.nashorn.internal.,\
-		   jdk.nashorn.tools.
+                   jdk.internal.,\
+                   jdk.nashorn.internal.,\
+                   jdk.nashorn.tools.
 
 #
 # Determines whether this properties file can be appended to
--- a/src/share/lib/security/java.security-macosx	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/lib/security/java.security-macosx	Tue Apr 16 05:11:50 2013 -0700
@@ -77,26 +77,57 @@
 security.provider.10=apple.security.AppleProvider
 
 #
-# Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by
-# the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity
-# algorithm is used.
+# Sun Provider SecureRandom seed source.
+#
+# Select the primary source of seed data for the "SHA1PRNG" and
+# "NativePRNG" SecureRandom implementations in the "Sun" provider.
+# (Other SecureRandom implementations might also use this property.)
+#
+# On Unix-like systems (for example, Solaris/Linux/MacOS), the
+# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from
+# special device files such as file:/dev/random.
 #
-# On Solaris and Linux systems, if file:/dev/urandom is specified and it
-# exists, a special SecureRandom implementation is activated by default.
-# This "NativePRNG" reads random bytes directly from /dev/urandom.
+# On Windows systems, specifying the URLs "file:/dev/random" or
+# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding
+# mechanism for SHA1PRNG.
+#
+# By default, an attempt is made to use the entropy gathering device
+# specified by the "securerandom.source" Security property.  If an
+# exception occurs while accessing the specified URL:
+#
+#     SHA1PRNG:
+#         the traditional system/thread activity algorithm will be used.
+#
+#     NativePRNG:
+#         a default value of /dev/random will be used.  If neither
+#         are available, the implementation will be disabled.
+#         "file" is the only currently supported protocol type.
 #
-# On Windows systems, the URLs file:/dev/random and file:/dev/urandom
-# enables use of the Microsoft CryptoAPI seed functionality.
+# The entropy gathering device can also be specified with the System
+# property "java.security.egd". For example:
+#
+#   % java -Djava.security.egd=file:/dev/random MainClass
 #
-securerandom.source=file:/dev/urandom
+# Specifying this System property will override the
+# "securerandom.source" Security property.
+#
+# In addition, if "file:/dev/random" or "file:/dev/urandom" is
+# specified, the "NativePRNG" implementation will be more preferred than
+# SHA1PRNG in the Sun provider.
 #
-# The entropy gathering device is described as a URL and can also
-# be specified with the system property "java.security.egd". For example,
-#   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source
-# setting.
+securerandom.source=file:/dev/random
+
+#
+# A list of known strong SecureRandom implementations.
+#
+# To help guide applications in selecting a suitable strong
+# java.security.SecureRandom implementation, Java distributions should
+# indicate a list of known strong implementations using the property.
+#
+# This is a comma-separated list of algorithm and/or algorithm:provider
+# entries.
+#
+securerandom.strongAlgorithms=NativePRNGBlocking:SUN
 
 #
 # Class to instantiate as the javax.security.auth.login.Configuration
@@ -160,9 +191,9 @@
                com.sun.org.glassfish.gmbal.,\
                com.oracle.xmlns.internal.,\
                com.oracle.webservices.internal.,\
-	       jdk.internal.,\
-	       jdk.nashorn.internal.,\
-	       jdk.nashorn.tools.,\
+               jdk.internal.,\
+               jdk.nashorn.internal.,\
+               jdk.nashorn.tools.,\
                apple.
 
 #
@@ -189,9 +220,9 @@
                    com.sun.org.glassfish.gmbal.,\
                    com.oracle.xmlns.internal.,\
                    com.oracle.webservices.internal.,\
-		   jdk.internal.,\
-		   jdk.nashorn.internal.,\
-		   jdk.nashorn.tools.,\
+                   jdk.internal.,\
+                   jdk.nashorn.internal.,\
+                   jdk.nashorn.tools.,\
                    apple.
 
 #
--- a/src/share/lib/security/java.security-solaris	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/lib/security/java.security-solaris	Tue Apr 16 05:11:50 2013 -0700
@@ -78,26 +78,57 @@
 security.provider.11=sun.security.smartcardio.SunPCSC
 
 #
-# Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by
-# the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity
-# algorithm is used.
+# Sun Provider SecureRandom seed source.
+#
+# Select the primary source of seed data for the "SHA1PRNG" and
+# "NativePRNG" SecureRandom implementations in the "Sun" provider.
+# (Other SecureRandom implementations might also use this property.)
+#
+# On Unix-like systems (for example, Solaris/Linux/MacOS), the
+# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from
+# special device files such as file:/dev/random.
 #
-# On Solaris and Linux systems, if file:/dev/urandom is specified and it
-# exists, a special SecureRandom implementation is activated by default.
-# This "NativePRNG" reads random bytes directly from /dev/urandom.
+# On Windows systems, specifying the URLs "file:/dev/random" or
+# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding
+# mechanism for SHA1PRNG.
+#
+# By default, an attempt is made to use the entropy gathering device
+# specified by the "securerandom.source" Security property.  If an
+# exception occurs while accessing the specified URL:
+#
+#     SHA1PRNG:
+#         the traditional system/thread activity algorithm will be used.
+#
+#     NativePRNG:
+#         a default value of /dev/random will be used.  If neither
+#         are available, the implementation will be disabled.
+#         "file" is the only currently supported protocol type.
 #
-# On Windows systems, the URLs file:/dev/random and file:/dev/urandom
-# enables use of the Microsoft CryptoAPI seed functionality.
+# The entropy gathering device can also be specified with the System
+# property "java.security.egd". For example:
+#
+#   % java -Djava.security.egd=file:/dev/random MainClass
 #
-securerandom.source=file:/dev/urandom
+# Specifying this System property will override the
+# "securerandom.source" Security property.
+#
+# In addition, if "file:/dev/random" or "file:/dev/urandom" is
+# specified, the "NativePRNG" implementation will be more preferred than
+# SHA1PRNG in the Sun provider.
 #
-# The entropy gathering device is described as a URL and can also
-# be specified with the system property "java.security.egd". For example,
-#   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source
-# setting.
+securerandom.source=file:/dev/random
+
+#
+# A list of known strong SecureRandom implementations.
+#
+# To help guide applications in selecting a suitable strong
+# java.security.SecureRandom implementation, Java distributions should
+# indicate a list of known strong implementations using the property.
+#
+# This is a comma-separated list of algorithm and/or algorithm:provider
+# entries.
+#
+securerandom.strongAlgorithms=NativePRNGBlocking:SUN
 
 #
 # Class to instantiate as the javax.security.auth.login.Configuration
@@ -161,9 +192,9 @@
                com.sun.org.glassfish.gmbal.,\
                com.oracle.xmlns.internal.,\
                com.oracle.webservices.internal.,\
-	       jdk.internal.,\
-	       jdk.nashorn.internal.,\
-	       jdk.nashorn.tools.
+               jdk.internal.,\
+               jdk.nashorn.internal.,\
+               jdk.nashorn.tools.
 
 #
 # List of comma-separated packages that start with or equal this string
@@ -189,9 +220,9 @@
                    com.sun.org.glassfish.gmbal.,\
                    com.oracle.xmlns.internal.,\
                    com.oracle.webservices.internal.,\
-		   jdk.internal.,\
-		   jdk.nashorn.internal.,\
-		   jdk.nashorn.tools.
+                   jdk.internal.,\
+                   jdk.nashorn.internal.,\
+                   jdk.nashorn.tools.
 
 #
 # Determines whether this properties file can be appended to
@@ -429,4 +460,4 @@
 #
 # Example:
 #   jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
-i
+
--- a/src/share/lib/security/java.security-windows	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/share/lib/security/java.security-windows	Tue Apr 16 05:11:50 2013 -0700
@@ -77,26 +77,57 @@
 security.provider.10=sun.security.mscapi.SunMSCAPI
 
 #
-# Select the source of seed data for SecureRandom. By default an
-# attempt is made to use the entropy gathering device specified by
-# the securerandom.source property. If an exception occurs when
-# accessing the URL then the traditional system/thread activity
-# algorithm is used.
+# Sun Provider SecureRandom seed source.
+#
+# Select the primary source of seed data for the "SHA1PRNG" and
+# "NativePRNG" SecureRandom implementations in the "Sun" provider.
+# (Other SecureRandom implementations might also use this property.)
+#
+# On Unix-like systems (for example, Solaris/Linux/MacOS), the
+# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from
+# special device files such as file:/dev/random.
 #
-# On Solaris and Linux systems, if file:/dev/urandom is specified and it
-# exists, a special SecureRandom implementation is activated by default.
-# This "NativePRNG" reads random bytes directly from /dev/urandom.
+# On Windows systems, specifying the URLs "file:/dev/random" or
+# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding
+# mechanism for SHA1PRNG.
+#
+# By default, an attempt is made to use the entropy gathering device
+# specified by the "securerandom.source" Security property.  If an
+# exception occurs while accessing the specified URL:
+#
+#     SHA1PRNG:
+#         the traditional system/thread activity algorithm will be used.
+#
+#     NativePRNG:
+#         a default value of /dev/random will be used.  If neither
+#         are available, the implementation will be disabled.
+#         "file" is the only currently supported protocol type.
 #
-# On Windows systems, the URLs file:/dev/random and file:/dev/urandom
-# enables use of the Microsoft CryptoAPI seed functionality.
+# The entropy gathering device can also be specified with the System
+# property "java.security.egd". For example:
+#
+#   % java -Djava.security.egd=file:/dev/random MainClass
 #
-securerandom.source=file:/dev/urandom
+# Specifying this System property will override the
+# "securerandom.source" Security property.
+#
+# In addition, if "file:/dev/random" or "file:/dev/urandom" is
+# specified, the "NativePRNG" implementation will be more preferred than
+# SHA1PRNG in the Sun provider.
 #
-# The entropy gathering device is described as a URL and can also
-# be specified with the system property "java.security.egd". For example,
-#   -Djava.security.egd=file:/dev/urandom
-# Specifying this system property will override the securerandom.source
-# setting.
+securerandom.source=file:/dev/random
+
+#
+# A list of known strong SecureRandom implementations.
+#
+# To help guide applications in selecting a suitable strong
+# java.security.SecureRandom implementation, Java distributions should
+# indicate a list of known strong implementations using the property.
+#
+# This is a comma-separated list of algorithm and/or algorithm:provider
+# entries.
+#
+securerandom.strongAlgorithms=Windows-PRNG:SunMSCAPI
 
 #
 # Class to instantiate as the javax.security.auth.login.Configuration
@@ -160,9 +191,9 @@
                com.sun.org.glassfish.gmbal.,\
                com.oracle.xmlns.internal.,\
                com.oracle.webservices.internal.,\
-	       jdk.internal.,\
-	       jdk.nashorn.internal.,\
-	       jdk.nashorn.tools.
+               jdk.internal.,\
+               jdk.nashorn.internal.,\
+               jdk.nashorn.tools.
 
 #
 # List of comma-separated packages that start with or equal this string
@@ -188,9 +219,9 @@
                    com.sun.org.glassfish.gmbal.,\
                    com.oracle.xmlns.internal.,\
                    com.oracle.webservices.internal.,\
-		   jdk.internal.,\
-		   jdk.nashorn.internal.,\
-		   jdk.nashorn.tools.
+                   jdk.internal.,\
+                   jdk.nashorn.internal.,\
+                   jdk.nashorn.tools.
 
 #
 # Determines whether this properties file can be appended to
--- a/src/solaris/classes/sun/security/provider/NativePRNG.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/solaris/classes/sun/security/provider/NativePRNG.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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
@@ -26,34 +26,47 @@
 package sun.security.provider;
 
 import java.io.*;
-
+import java.net.*;
 import java.security.*;
-import java.security.SecureRandom;
+import sun.security.util.Debug;
 
 /**
- * Native PRNG implementation for Solaris/Linux. It interacts with
- * /dev/random and /dev/urandom, so it is only available if those
- * files are present. Otherwise, SHA1PRNG is used instead of this class.
- *
- * getSeed() and setSeed() directly read/write /dev/random. However,
- * /dev/random is only writable by root in many configurations. Because
- * we cannot just ignore bytes specified via setSeed(), we keep a
- * SHA1PRNG around in parallel.
- *
- * nextBytes() reads the bytes directly from /dev/urandom (and then
- * mixes them with bytes from the SHA1PRNG for the reasons explained
- * above). Reading bytes from /dev/urandom means that constantly get
- * new entropy the operating system has collected. This is a notable
- * advantage over the SHA1PRNG model, which acquires entropy only
- * initially during startup although the VM may be running for months.
- *
- * Also note that we do not need any initial pure random seed from
- * /dev/random. This is an advantage because on some versions of Linux
- * it can be exhausted very quickly and could thus impact startup time.
- *
+ * Native PRNG implementation for Solaris/Linux/MacOS.
+ * <p>
+ * It obtains seed and random numbers by reading system files such as
+ * the special device files /dev/random and /dev/urandom.  This
+ * implementation respects the {@code securerandom.source} Security
+ * property and {@code java.security.egd} System property for obtaining
+ * seed material.  If the file specified by the properties does not
+ * exist, /dev/random is the default seed source.  /dev/urandom is
+ * the default source of random numbers.
+ * <p>
+ * On some Unix platforms, /dev/random may block until enough entropy is
+ * available, but that may negatively impact the perceived startup
+ * time.  By selecting these sources, this implementation tries to
+ * strike a balance between performance and security.
+ * <p>
+ * generateSeed() and setSeed() attempt to directly read/write to the seed
+ * source. However, this file may only be writable by root in many
+ * configurations. Because we cannot just ignore bytes specified via
+ * setSeed(), we keep a SHA1PRNG around in parallel.
+ * <p>
+ * nextBytes() reads the bytes directly from the source of random
+ * numbers (and then mixes them with bytes from the SHA1PRNG for the
+ * reasons explained above). Reading bytes from the random generator means
+ * that we are generally getting entropy from the operating system. This
+ * is a notable advantage over the SHA1PRNG model, which acquires
+ * entropy only initially during startup although the VM may be running
+ * for months.
+ * <p>
+ * Also note for nextBytes() that we do not need any initial pure random
+ * seed from /dev/random. This is an advantage because on some versions
+ * of Linux entropy can be exhausted very quickly and could thus impact
+ * startup time.
+ * <p>
  * Finally, note that we use a singleton for the actual work (RandomIO)
  * to avoid having to open and close /dev/[u]random constantly. However,
- * there may me many NativePRNG instances created by the JCA framework.
+ * there may be many NativePRNG instances created by the JCA framework.
  *
  * @since   1.5
  * @author  Andreas Sterbenz
@@ -62,32 +75,121 @@
 
     private static final long serialVersionUID = -6599091113397072932L;
 
+    private static final Debug debug = Debug.getInstance("provider");
+
     // name of the pure random file (also used for setSeed())
     private static final String NAME_RANDOM = "/dev/random";
     // name of the pseudo random file
     private static final String NAME_URANDOM = "/dev/urandom";
 
+    // which kind of RandomIO object are we creating?
+    private enum Variant {
+        MIXED, BLOCKING, NONBLOCKING
+    }
+
     // singleton instance or null if not available
-    private static final RandomIO INSTANCE = initIO();
+    private static final RandomIO INSTANCE = initIO(Variant.MIXED);
 
-    private static RandomIO initIO() {
-        return AccessController.doPrivileged(
-            new PrivilegedAction<RandomIO>() {
-                public RandomIO run() {
-                File randomFile = new File(NAME_RANDOM);
-                if (randomFile.exists() == false) {
+    /**
+     * Get the System egd source (if defined).  We only allow "file:"
+     * URLs for now. If there is a egd value, parse it.
+     *
+     * @return the URL or null if not available.
+     */
+    private static URL getEgdUrl() {
+        // This will return "" if nothing was set.
+        String egdSource = SunEntries.getSeedSource();
+        URL egdUrl;
+
+        if (egdSource.length() != 0) {
+            if (debug != null) {
+                debug.println("NativePRNG egdUrl: " + egdSource);
+            }
+            try {
+                egdUrl = new URL(egdSource);
+                if (!egdUrl.getProtocol().equalsIgnoreCase("file")) {
                     return null;
                 }
-                File urandomFile = new File(NAME_URANDOM);
-                if (urandomFile.exists() == false) {
-                    return null;
+            } catch (MalformedURLException e) {
+                return null;
+            }
+        } else {
+            egdUrl = null;
+        }
+
+        return egdUrl;
+    }
+
+    /**
+     * Create a RandomIO object for all I/O of this Variant type.
+     */
+    private static RandomIO initIO(final Variant v) {
+        return AccessController.doPrivileged(
+            new PrivilegedAction<RandomIO>() {
+                @Override
+                public RandomIO run() {
+
+                    File seedFile;
+                    File nextFile;
+
+                    switch(v) {
+                    case MIXED:
+                        URL egdUrl;
+                        File egdFile = null;
+
+                        if ((egdUrl = getEgdUrl()) != null) {
+                            try {
+                                egdFile = SunEntries.getDeviceFile(egdUrl);
+                            } catch (IOException e) {
+                                // Swallow, seedFile is still null
+                            }
+                        }
+
+                        // Try egd first.
+                        if ((egdFile != null) && egdFile.canRead()) {
+                            seedFile = egdFile;
+                        } else {
+                            // fall back to /dev/random.
+                            seedFile = new File(NAME_RANDOM);
+                        }
+                        nextFile = new File(NAME_URANDOM);
+                        break;
+
+                    case BLOCKING:
+                        seedFile = new File(NAME_RANDOM);
+                        nextFile = new File(NAME_RANDOM);
+                        break;
+
+                    case NONBLOCKING:
+                        seedFile = new File(NAME_URANDOM);
+                        nextFile = new File(NAME_URANDOM);
+                        break;
+
+                    default:
+                        // Shouldn't happen!
+                        return null;
+                    }
+
+                    if (debug != null) {
+                        debug.println("NativePRNG." + v +
+                            " seedFile: " + seedFile +
+                            " nextFile: " + nextFile);
+                    }
+
+                    if (!seedFile.canRead() || !nextFile.canRead()) {
+                        if (debug != null) {
+                            debug.println("NativePRNG." + v +
+                                " Couldn't read Files.");
+                        }
+                        return null;
+                    }
+
+                    try {
+                        return new RandomIO(seedFile, nextFile);
+                    } catch (Exception e) {
+                        return null;
+                    }
                 }
-                try {
-                    return new RandomIO(randomFile, urandomFile);
-                } catch (Exception e) {
-                    return null;
-                }
-            }
         });
     }
 
@@ -105,67 +207,173 @@
     }
 
     // set the seed
+    @Override
     protected void engineSetSeed(byte[] seed) {
         INSTANCE.implSetSeed(seed);
     }
 
     // get pseudo random bytes
+    @Override
     protected void engineNextBytes(byte[] bytes) {
         INSTANCE.implNextBytes(bytes);
     }
 
     // get true random bytes
+    @Override
     protected byte[] engineGenerateSeed(int numBytes) {
         return INSTANCE.implGenerateSeed(numBytes);
     }
 
     /**
+     * A NativePRNG-like class that uses /dev/random for both
+     * seed and random material.
+     *
+     * Note that it does not respect the egd properties, since we have
+     * no way of knowing what those qualities are.
+     *
+     * This is very similar to the outer NativePRNG class, minimizing any
+     * breakage to the serialization of the existing implementation.
+     *
+     * @since   1.8
+     */
+    public static final class Blocking extends SecureRandomSpi {
+        private static final long serialVersionUID = -6396183145759983347L;
+
+        private static final RandomIO INSTANCE = initIO(Variant.BLOCKING);
+
+        // return whether this is available
+        static boolean isAvailable() {
+            return INSTANCE != null;
+        }
+
+        // constructor, called by the JCA framework
+        public Blocking() {
+            super();
+            if (INSTANCE == null) {
+                throw new AssertionError("NativePRNG$Blocking not available");
+            }
+        }
+
+        // set the seed
+        @Override
+        protected void engineSetSeed(byte[] seed) {
+            INSTANCE.implSetSeed(seed);
+        }
+
+        // get pseudo random bytes
+        @Override
+        protected void engineNextBytes(byte[] bytes) {
+            INSTANCE.implNextBytes(bytes);
+        }
+
+        // get true random bytes
+        @Override
+        protected byte[] engineGenerateSeed(int numBytes) {
+            return INSTANCE.implGenerateSeed(numBytes);
+        }
+    }
+
+    /**
+     * A NativePRNG-like class that uses /dev/urandom for both
+     * seed and random material.
+     *
+     * Note that it does not respect the egd properties, since we have
+     * no way of knowing what those qualities are.
+     *
+     * This is very similar to the outer NativePRNG class, minimizing any
+     * breakage to the serialization of the existing implementation.
+     *
+     * @since   1.8
+     */
+    public static final class NonBlocking extends SecureRandomSpi {
+        private static final long serialVersionUID = -1102062982994105487L;
+
+        private static final RandomIO INSTANCE = initIO(Variant.NONBLOCKING);
+
+        // return whether this is available
+        static boolean isAvailable() {
+            return INSTANCE != null;
+        }
+
+        // constructor, called by the JCA framework
+        public NonBlocking() {
+            super();
+            if (INSTANCE == null) {
+                throw new AssertionError(
+                    "NativePRNG$NonBlocking not available");
+            }
+        }
+
+        // set the seed
+        @Override
+        protected void engineSetSeed(byte[] seed) {
+            INSTANCE.implSetSeed(seed);
+        }
+
+        // get pseudo random bytes
+        @Override
+        protected void engineNextBytes(byte[] bytes) {
+            INSTANCE.implNextBytes(bytes);
+        }
+
+        // get true random bytes
+        @Override
+        protected byte[] engineGenerateSeed(int numBytes) {
+            return INSTANCE.implGenerateSeed(numBytes);
+        }
+    }
+
+    /**
      * Nested class doing the actual work. Singleton, see INSTANCE above.
      */
     private static class RandomIO {
 
-        // we buffer data we read from /dev/urandom for efficiency,
+        // we buffer data we read from the "next" file for efficiency,
         // but we limit the lifetime to avoid using stale bits
         // lifetime in ms, currently 100 ms (0.1 s)
         private final static long MAX_BUFFER_TIME = 100;
 
-        // size of the /dev/urandom buffer
+        // size of the "next" buffer
         private final static int BUFFER_SIZE = 32;
 
-        // In/OutputStream for /dev/random and /dev/urandom
-        private final InputStream randomIn, urandomIn;
-        private OutputStream randomOut;
+        // Holder for the seedFile.  Used if we ever add seed material.
+        File seedFile;
 
-        // flag indicating if we have tried to open randomOut yet
-        private boolean randomOutInitialized;
+        // In/OutputStream for "seed" and "next"
+        private final InputStream seedIn, nextIn;
+        private OutputStream seedOut;
+
+        // flag indicating if we have tried to open seedOut yet
+        private boolean seedOutInitialized;
 
         // SHA1PRNG instance for mixing
         // initialized lazily on demand to avoid problems during startup
         private volatile sun.security.provider.SecureRandom mixRandom;
 
-        // buffer for /dev/urandom bits
-        private final byte[] urandomBuffer;
+        // buffer for next bits
+        private final byte[] nextBuffer;
 
-        // number of bytes left in urandomBuffer
+        // number of bytes left in nextBuffer
         private int buffered;
 
-        // time we read the data into the urandomBuffer
+        // time we read the data into the nextBuffer
         private long lastRead;
 
         // mutex lock for nextBytes()
         private final Object LOCK_GET_BYTES = new Object();
 
-        // mutex lock for getSeed()
+        // mutex lock for generateSeed()
         private final Object LOCK_GET_SEED = new Object();
 
         // mutex lock for setSeed()
         private final Object LOCK_SET_SEED = new Object();
 
         // constructor, called only once from initIO()
-        private RandomIO(File randomFile, File urandomFile) throws IOException {
-            randomIn = new FileInputStream(randomFile);
-            urandomIn = new FileInputStream(urandomFile);
-            urandomBuffer = new byte[BUFFER_SIZE];
+        private RandomIO(File seedFile, File nextFile) throws IOException {
+            this.seedFile = seedFile;
+            seedIn = new FileInputStream(seedFile);
+            nextIn = new FileInputStream(nextFile);
+            nextBuffer = new byte[BUFFER_SIZE];
         }
 
         // get the SHA1PRNG for mixing
@@ -179,7 +387,7 @@
                         r = new sun.security.provider.SecureRandom();
                         try {
                             byte[] b = new byte[20];
-                            readFully(urandomIn, b);
+                            readFully(nextIn, b);
                             r.engineSetSeed(b);
                         } catch (IOException e) {
                             throw new ProviderException("init failed", e);
@@ -192,7 +400,7 @@
         }
 
         // read data.length bytes from in
-        // /dev/[u]random are not normal files, so we need to loop the read.
+        // These are not normal files, so we need to loop the read.
         // just keep trying as long as we are making progress
         private static void readFully(InputStream in, byte[] data)
                 throws IOException {
@@ -201,22 +409,22 @@
             while (len > 0) {
                 int k = in.read(data, ofs, len);
                 if (k <= 0) {
-                    throw new EOFException("/dev/[u]random closed?");
+                    throw new EOFException("File(s) closed?");
                 }
                 ofs += k;
                 len -= k;
             }
             if (len > 0) {
-                throw new IOException("Could not read from /dev/[u]random");
+                throw new IOException("Could not read from file(s)");
             }
         }
 
-        // get true random bytes, just read from /dev/random
+        // get true random bytes, just read from "seed"
         private byte[] implGenerateSeed(int numBytes) {
             synchronized (LOCK_GET_SEED) {
                 try {
                     byte[] b = new byte[numBytes];
-                    readFully(randomIn, b);
+                    readFully(seedIn, b);
                     return b;
                 } catch (IOException e) {
                     throw new ProviderException("generateSeed() failed", e);
@@ -225,26 +433,27 @@
         }
 
         // supply random bytes to the OS
-        // write to /dev/random if possible
+        // write to "seed" if possible
         // always add the seed to our mixing random
         private void implSetSeed(byte[] seed) {
             synchronized (LOCK_SET_SEED) {
-                if (randomOutInitialized == false) {
-                    randomOutInitialized = true;
-                    randomOut = AccessController.doPrivileged(
+                if (seedOutInitialized == false) {
+                    seedOutInitialized = true;
+                    seedOut = AccessController.doPrivileged(
                             new PrivilegedAction<OutputStream>() {
+                        @Override
                         public OutputStream run() {
                             try {
-                                return new FileOutputStream(NAME_RANDOM, true);
+                                return new FileOutputStream(seedFile, true);
                             } catch (Exception e) {
                                 return null;
                             }
                         }
                     });
                 }
-                if (randomOut != null) {
+                if (seedOut != null) {
                     try {
-                        randomOut.write(seed);
+                        seedOut.write(seed);
                     } catch (IOException e) {
                         throw new ProviderException("setSeed() failed", e);
                     }
@@ -261,12 +470,12 @@
                 return;
             }
             lastRead = time;
-            readFully(urandomIn, urandomBuffer);
-            buffered = urandomBuffer.length;
+            readFully(nextIn, nextBuffer);
+            buffered = nextBuffer.length;
         }
 
         // get pseudo random bytes
-        // read from /dev/urandom and XOR with bytes generated by the
+        // read from "next" and XOR with bytes generated by the
         // mixing SHA1PRNG
         private void implNextBytes(byte[] data) {
             synchronized (LOCK_GET_BYTES) {
@@ -276,9 +485,9 @@
                     int ofs = 0;
                     while (len > 0) {
                         ensureBufferValid();
-                        int bufferOfs = urandomBuffer.length - buffered;
+                        int bufferOfs = nextBuffer.length - buffered;
                         while ((len > 0) && (buffered > 0)) {
-                            data[ofs++] ^= urandomBuffer[bufferOfs++];
+                            data[ofs++] ^= nextBuffer[bufferOfs++];
                             len--;
                             buffered--;
                         }
@@ -288,7 +497,5 @@
                 }
             }
         }
-
     }
-
 }
--- a/src/solaris/classes/sun/security/provider/NativeSeedGenerator.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/solaris/classes/sun/security/provider/NativeSeedGenerator.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, 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
@@ -34,8 +34,8 @@
  */
 class NativeSeedGenerator extends SeedGenerator.URLSeedGenerator {
 
-    NativeSeedGenerator() throws IOException {
-        super();
+    NativeSeedGenerator(String seedFile) throws IOException {
+        super(seedFile);
     }
 
 }
--- a/src/windows/classes/sun/security/mscapi/PRNG.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/windows/classes/sun/security/mscapi/PRNG.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, 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
@@ -58,6 +58,7 @@
      *
      * @param seed the seed.
      */
+    @Override
     protected void engineSetSeed(byte[] seed) {
         if (seed != null) {
             generateSeed(-1, seed);
@@ -69,6 +70,7 @@
      *
      * @param bytes the array to be filled in with random bytes.
      */
+    @Override
     protected void engineNextBytes(byte[] bytes) {
         if (bytes != null) {
             if (generateSeed(0, bytes) == null) {
@@ -85,6 +87,7 @@
      *
      * @return the seed bytes.
      */
+    @Override
     protected byte[] engineGenerateSeed(int numBytes) {
         byte[] seed = generateSeed(numBytes, null);
 
--- a/src/windows/classes/sun/security/provider/NativePRNG.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/windows/classes/sun/security/provider/NativePRNG.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, 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
@@ -39,4 +39,15 @@
         return false;
     }
 
+    public static final class NonBlocking {
+        static boolean isAvailable() {
+            return false;
+        }
+    }
+
+    public static final class Blocking {
+        static boolean isAvailable() {
+            return false;
+        }
+    }
 }
--- a/src/windows/classes/sun/security/provider/NativeSeedGenerator.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/src/windows/classes/sun/security/provider/NativeSeedGenerator.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, 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
@@ -39,7 +39,8 @@
      * @exception IOException if CryptoAPI seeds are not available
      * on this platform.
      */
-    NativeSeedGenerator() throws IOException {
+    NativeSeedGenerator(String seedFile) throws IOException {
+        // seedFile is ignored.
         super();
         // try generating two random bytes to see if CAPI is available
         if (!nativeGenerateSeed(new byte[2])) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/PBE/NegativeLength.java	Tue Apr 16 05:11:50 2013 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, 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
+ * @bug 8001596
+ * @summary Incorrect condition check in PBKDF2KeyImpl.java
+ */
+
+import java.security.*;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.lang.reflect.*;
+
+public class NegativeLength {
+
+    public static void main(String[] args) throws Exception {
+        SecretKeyFactory skf = SecretKeyFactory.getInstance(
+            "PBKDF2WithHmacSHA1", "SunJCE");
+
+        // Create a valid PBEKeySpec
+        PBEKeySpec pbeks = new PBEKeySpec(
+            new char['p'], new byte[1], 1024, 8);
+
+        // Use reflection to set it negative.
+        Class c = pbeks.getClass();
+        Field f = c.getDeclaredField("keyLength");
+        f.setAccessible(true);
+        f.setInt(pbeks, -8);
+
+        System.out.println("pbeks.getKeyLength(): " + pbeks.getKeyLength());
+
+        try {
+
+            // A negative length is clearly wrong, we should get a
+            // InvalidKeySpecException.  Anything else is wrong.
+            skf.generateSecret(pbeks);
+            throw new Exception("We shouldn't get here.");
+        } catch (InvalidKeySpecException ike) {
+            // swallow, this is the exception we want.
+            System.out.println("Test Passed.");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/sun/crypto/provider/Cipher/UTIL/SunJCEGetInstance.java	Tue Apr 16 05:11:50 2013 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013, 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
+ * @bug 7171982
+ * @summary Test that SunJCE.getInstance() is retrieving a provider when
+ * SunJCE has been removed from the provider list.
+ * @run main/othervm SunJCEGetInstance
+ */
+
+import java.security.Security;
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+
+public class SunJCEGetInstance {
+    public static void main(String[] args) throws Exception {
+        Cipher jce;
+
+        try{
+            // Remove SunJCE from Provider list
+            Security.removeProvider("SunJCE");
+
+            // Create our own instance of SunJCE provider.  Purposefully not
+            // using SunJCE.getInstance() so we can have our own instance
+            // for the test.
+            jce = Cipher.getInstance("AES/CBC/PKCS5Padding",
+                new com.sun.crypto.provider.SunJCE());
+
+            jce.init(Cipher.ENCRYPT_MODE,
+                new SecretKeySpec("1234567890abcedf".getBytes(), "AES"));
+            jce.doFinal("PlainText".getBytes());
+        } catch (Exception e) {
+            System.err.println("Setup failure:  ");
+            throw e;
+        }
+
+        // Get parameters which will call SunJCE.getInstance().  Failure
+        // would occur on this line.
+        try {
+            jce.getParameters().getEncoded();
+
+        } catch (Exception e) {
+            System.err.println("Test Failure");
+            throw e;
+        }
+        System.out.println("Passed");
+    }
+}
--- a/test/sun/security/ec/TestEC.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/test/sun/security/ec/TestEC.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, 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
@@ -21,6 +21,11 @@
  * questions.
  */
 
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
 /**
  * @test
  * @bug 6840752
@@ -30,7 +35,7 @@
  * @library ../pkcs11/sslecc
  * @library ../../../java/security/testlibrary
  * @compile -XDignore.symbol.file TestEC.java
- * @run main TestEC
+ * @run main/othervm TestEC
  */
 
 import java.security.NoSuchProviderException;
--- a/test/sun/security/pkcs11/fips/CipherTest.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/test/sun/security/pkcs11/fips/CipherTest.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, 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
@@ -147,6 +147,25 @@
             CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256",     0x0303, 0xFFFF),
             CS_17("TLS_RSA_WITH_NULL_SHA256",                0x0303, 0xFFFF),
 
+            CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
+            CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
+            CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",   0x0303, 0xFFFF),
+            CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384",         0x0303, 0xFFFF),
+            CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",  0x0303, 0xFFFF),
+            CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",    0x0303, 0xFFFF),
+            CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+            CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+
+            CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",   0x0303, 0xFFFF),
+            CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256",         0x0303, 0xFFFF),
+            CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",  0x0303, 0xFFFF),
+            CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",    0x0303, 0xFFFF),
+            CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+            CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+
+            CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+            CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+
             // cipher suites obsoleted since TLS 1.2
             CS_50("SSL_RSA_WITH_DES_CBC_SHA",                0x0000, 0x0303),
             CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA",            0x0000, 0x0303),
--- a/test/sun/security/pkcs11/sslecc/CipherTest.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/test/sun/security/pkcs11/sslecc/CipherTest.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, 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
@@ -147,6 +147,25 @@
             CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256",     0x0303, 0xFFFF),
             CS_17("TLS_RSA_WITH_NULL_SHA256",                0x0303, 0xFFFF),
 
+            CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
+            CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
+            CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",   0x0303, 0xFFFF),
+            CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384",         0x0303, 0xFFFF),
+            CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",  0x0303, 0xFFFF),
+            CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",    0x0303, 0xFFFF),
+            CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+            CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+
+            CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",   0x0303, 0xFFFF),
+            CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256",         0x0303, 0xFFFF),
+            CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",  0x0303, 0xFFFF),
+            CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",    0x0303, 0xFFFF),
+            CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+            CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+
+            CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+            CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+
             // cipher suites obsoleted since TLS 1.2
             CS_50("SSL_RSA_WITH_DES_CBC_SHA",                0x0000, 0x0303),
             CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA",            0x0000, 0x0303),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/SecureRandom/StrongSecureRandom.java	Tue Apr 16 05:11:50 2013 -0700
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2013, 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
+ * @bug 6425477
+ * @summary Better support for generation of high entropy random numbers
+ * @run main/othervm StrongSecureRandom
+ */
+import java.security.*;
+import java.util.*;
+
+/**
+ * This test assumes that the standard Sun providers are installed.
+ */
+public class StrongSecureRandom {
+
+    private static String os = System.getProperty("os.name", "unknown");
+
+    private static void testDefaultEgd() throws Exception {
+        // No SecurityManager installed.
+        String s = Security.getProperty("securerandom.source");
+
+        System.out.println("Testing:  default EGD: " + s);
+        if (!s.equals("file:/dev/random")) {
+            throw new Exception("Default is not 'file:/dev/random'");
+        }
+    }
+
+    private static void testSHA1PRNGImpl() throws Exception {
+        SecureRandom sr;
+        byte[] ba;
+
+        String urandom = "file:/dev/urandom";
+
+        System.out.println("Testing new SeedGenerator and EGD");
+
+        Security.setProperty("securerandom.source", urandom);
+        if (!Security.getProperty("securerandom.source").equals(urandom)) {
+            throw new Exception("Couldn't set securerandom.source");
+        }
+
+        /*
+         * Take out a large number of bytes in hopes of blocking.
+         * Don't expect this to happen, unless something is broken on Linux
+         */
+        sr = SecureRandom.getInstance("SHA1PRNG");
+        if (!sr.getAlgorithm().equals("SHA1PRNG")) {
+            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
+        }
+
+        ba = sr.generateSeed(4096);
+        sr.nextBytes(ba);
+        sr.setSeed(ba);
+    }
+
+    private static void testNativePRNGImpls() throws Exception {
+        SecureRandom sr;
+        byte[] ba;
+
+        System.out.println("Testing new NativePRNGImpls");
+
+        if (os.startsWith("Windows")) {
+            System.out.println("Skip windows testing.");
+            return;
+        }
+
+        System.out.println("    Testing regular");
+        sr = SecureRandom.getInstance("NativePRNG");
+        if (!sr.getAlgorithm().equals("NativePRNG")) {
+            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
+        }
+        ba = sr.generateSeed(1);
+        sr.nextBytes(ba);
+        sr.setSeed(ba);
+
+        System.out.println("    Testing NonBlocking");
+        sr = SecureRandom.getInstance("NativePRNGNonBlocking");
+        if (!sr.getAlgorithm().equals("NativePRNGNonBlocking")) {
+            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
+        }
+        ba = sr.generateSeed(1);
+        sr.nextBytes(ba);
+        sr.setSeed(ba);
+
+        if (os.equals("Linux")) {
+            System.out.println("Skip Linux blocking test.");
+            return;
+        }
+
+        System.out.println("    Testing Blocking");
+        sr = SecureRandom.getInstance("NativePRNGBlocking");
+        if (!sr.getAlgorithm().equals("NativePRNGBlocking")) {
+            throw new Exception("sr.getAlgorithm(): " + sr.getAlgorithm());
+        }
+        ba = sr.generateSeed(1);
+        sr.nextBytes(ba);
+        sr.setSeed(ba);
+    }
+
+    private static void testStrongInstance(boolean expected) throws Exception {
+
+        boolean result = (SecureRandom.getStrongSecureRandom() != null);
+
+        if (expected != result) {
+            throw new Exception("Received: " + result);
+        }
+    }
+
+    /*
+     * This test assumes that the standard providers are installed.
+     */
+    private static void testProperty(String property, boolean expected)
+            throws Exception {
+
+        System.out.println("Testing: '" + property + "' " + expected);
+
+        Security.setProperty("securerandom.strongAlgorithms", property);
+        testStrongInstance(expected);
+    }
+
+    private static void testProperties() throws Exception {
+        // Sets securerandom.strongAlgorithms, and then tests various combos.
+        testProperty("", false);
+
+        testProperty("SHA1PRNG", true);
+        testProperty(" SHA1PRNG", true);
+        testProperty("SHA1PRNG ", true);
+        testProperty(" SHA1PRNG ", true);
+
+        // Impls are case-insenstive, providers are sensitive.
+        testProperty("SHA1PRNG:SUN", true);
+        testProperty("Sha1PRNG:SUN", true);
+        testProperty("SHA1PRNG:Sun", false);
+
+        testProperty(" SHA1PRNG:SUN", true);
+        testProperty("SHA1PRNG:SUN ", true);
+        testProperty(" SHA1PRNG:SUN ", true);
+
+        testProperty(" SHA1PRNG:SUn", false);
+        testProperty("SHA1PRNG:SUn ", false);
+        testProperty(" SHA1PRNG:SUn ", false);
+
+        testProperty(",,,SHA1PRNG", true);
+        testProperty(",,, SHA1PRNG", true);
+        testProperty(" , , ,SHA1PRNG ", true);
+
+        testProperty(",,,, SHA1PRNG ,,,", true);
+        testProperty(",,,, SHA1PRNG:SUN ,,,", true);
+        testProperty(",,,, SHA1PRNG:SUn ,,,", false);
+
+        testProperty(",,,SHA1PRNG:Sun,, SHA1PRNG:SUN", true);
+        testProperty(",,,Sha1PRNG:Sun, SHA1PRNG:SUN", true);
+        testProperty(" SHA1PRNG:Sun, Sha1PRNG:Sun,,,,Sha1PRNG:SUN", true);
+
+        testProperty(",,,SHA1PRNG:Sun,, SHA1PRNG:SUn", false);
+        testProperty(",,,Sha1PRNG:Sun, SHA1PRNG:SUn", false);
+        testProperty(" SHA1PRNG:Sun, Sha1PRNG:Sun,,,,Sha1PRNG:SUn", false);
+
+        testProperty(
+                " @#%,%$#:!%^, NativePRNG:Sun, Sha1PRNG:Sun,,Sha1PRNG:SUN",
+                true);
+        testProperty(" @#%,%$#!%^, NativePRNG:Sun, Sha1PRNG:Sun,,Sha1PRNG:SUn",
+                false);
+    }
+
+    /*
+     * Linux tends to block, so ignore anything that reads /dev/random.
+     */
+    private static void handleLinuxRead(SecureRandom sr) throws Exception {
+        if (os.equals("Linux")) {
+            if (!sr.getAlgorithm().equalsIgnoreCase("NativePRNGBlocking")) {
+                sr.nextBytes(new byte[34]);
+            }
+        } else {
+            sr.nextBytes(new byte[34]);
+            sr.generateSeed(34);
+            sr.setSeed(new byte[34]);
+        }
+    }
+
+    /*
+     * This is duplicating stuff above, but just iterate over all impls
+     * just in case we missed something.
+     */
+    private static void testAllImpls() throws Exception {
+        System.out.print("Testing:  AllImpls:  ");
+
+        Iterator<String> i = Security.getAlgorithms("SecureRandom").iterator();
+
+        while (i.hasNext()) {
+            String s = i.next();
+            System.out.print("/" + s);
+            SecureRandom sr = SecureRandom.getInstance(s);
+
+            handleLinuxRead(sr);
+            handleLinuxRead(sr);
+        }
+        System.out.println("/");
+    }
+
+    public static void main(String args[]) throws Exception {
+        testDefaultEgd();
+        testSHA1PRNGImpl();
+        testNativePRNGImpls();
+        testAllImpls();
+
+        // test default.
+        testStrongInstance(true);
+        testProperties();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/SecureRandom/StrongSeedReader.java	Tue Apr 16 05:11:50 2013 -0700
@@ -0,0 +1,81 @@
+ /*
+ * Copyright (c) 2013, 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
+ * @bug 6425477
+ * @summary Better support for generation of high entropy random numbers
+ * @run main/othervm StrongSeedReader
+ */
+
+import java.io.*;
+import java.net.*;
+import java.security.SecureRandom;
+
+/**
+ * A simple test which takes into account knowledge about the underlying
+ * implementation. This may change if the implementations change.
+ *
+ * Create a new EGD file with known bytes, then set the EGD System property. The
+ * data read should be the same as what was written.
+ */
+public class StrongSeedReader {
+
+    public static void main(String[] args) throws Exception {
+        // Skip Windows, the SHA1PRNG uses CryptGenRandom.
+        if (System.getProperty("os.name", "unknown").startsWith("Windows")) {
+            return;
+        }
+
+        File file = null;
+        try {
+            file = new File(System.getProperty("java.io.tmpdir") +
+                    "StrongSeedReader.tmpdata");
+
+            // write a bunch of 0's to the file.
+            FileOutputStream fos = new FileOutputStream(file);
+            fos.write(new byte[2048]);
+
+            System.setProperty("java.security.egd", file.toURI().toString());
+            testSeed("NativePRNG");
+            testSeed("SHA1PRNG");
+        } finally {
+            if (file != null) {
+                file.delete();
+            }
+        }
+    }
+
+    private static void testSeed(String alg) throws Exception {
+        System.out.println("Testing: " + alg);
+        SecureRandom sr = SecureRandom.getInstance(alg);
+        byte[] ba = sr.generateSeed(20);
+
+        // We should get back a bunch of zeros from the file.
+        for (byte b : ba) {
+            if (b != 0) {
+                throw new Exception("Byte != 0");
+            }
+        }
+    }
+}
--- a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, 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
@@ -21,14 +21,16 @@
  * questions.
  */
 
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
 /*
  * @test
  * @bug 7031830
  * @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine
  * @run main/othervm SSLEngineBadBufferArrayAccess
- *
- *     SunJSSE does not support dynamic system properties, no way to re-use
- *     system properties in samevm/agentvm mode.
  */
 
 /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/ssl/javax/net/ssl/TLSv12/ShortRSAKeyGCM.java	Tue Apr 16 05:11:50 2013 -0700
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2012, 2013, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 7030966
+ * @summary Support AEAD CipherSuites
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_128_GCM_SHA256
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_128_GCM_SHA256
+ */
+
+/*
+ * Need additional key materials to run the following cases.
+ *
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *
+ * Need unlimited JCE Unlimited Strength Jurisdiction Policy to run the
+ * following cases.
+ *
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_RSA_WITH_AES_256_GCM_SHA384
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ * @run main/othervm ShortRSAKeyGCM PKIX TLS_DH_anon_WITH_AES_256_GCM_SHA384
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+import javax.net.ssl.*;
+import java.security.Security;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import sun.misc.BASE64Decoder;
+
+
+public class ShortRSAKeyGCM {
+
+    /*
+     * =============================================================
+     * Set the various variables needed for the tests, then
+     * specify what tests to run on each side.
+     */
+
+    /*
+     * Should we run the client or server in a separate thread?
+     * Both sides can throw exceptions, but do you have a preference
+     * as to which side should be the main thread.
+     */
+    static boolean separateServerThread = true;
+
+    /*
+     * Where do we find the keystores?
+     */
+    // Certificates and key used in the test.
+    static String trustedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
+        "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
+        "MTEwODE5MDE1MjE5WhcNMzIwNzI5MDE1MjE5WjA7MQswCQYDVQQGEwJVUzENMAsG\n" +
+        "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" +
+        "KoZIhvcNAQEBBQADgY0AMIGJAoGBAM8orG08DtF98TMSscjGsidd1ZoN4jiDpi8U\n" +
+        "ICz+9dMm1qM1d7O2T+KH3/mxyox7Rc2ZVSCaUD0a3CkhPMnlAx8V4u0H+E9sqso6\n" +
+        "iDW3JpOyzMExvZiRgRG/3nvp55RMIUV4vEHOZ1QbhuqG4ebN0Vz2DkRft7+flthf\n" +
+        "vDld6f5JAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLl81dnfp0wDrv0OJ1sxlWzH83Xh\n" +
+        "MGMGA1UdIwRcMFqAFLl81dnfp0wDrv0OJ1sxlWzH83XhoT+kPTA7MQswCQYDVQQG\n" +
+        "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
+        "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" +
+        "BQADgYEALlgaH1gWtoBZ84EW8Hu6YtGLQ/L9zIFmHonUPZwn3Pr//icR9Sqhc3/l\n" +
+        "pVTxOINuFHLRz4BBtEylzRIOPzK3tg8XwuLb1zd0db90x3KBCiAL6E6cklGEPwLe\n" +
+        "XYMHDn9eDsaq861Tzn6ZwzMgw04zotPMoZN0mVd/3Qca8UJFucE=\n" +
+        "-----END CERTIFICATE-----";
+
+    static String targetCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICNDCCAZ2gAwIBAgIBDDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" +
+        "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" +
+        "MTExMTA3MTM1NTUyWhcNMzEwNzI1MTM1NTUyWjBPMQswCQYDVQQGEwJVUzENMAsG\n" +
+        "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" +
+        "BAMTCWxvY2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC3Pb49OSPfOD2G\n" +
+        "HSXFCFx1GJEZfqG9ZUf7xuIi/ra5dLjPGAaoY5QF2QOa8VnOriQCXDfyXHxsuRnE\n" +
+        "OomxL7EVAgMBAAGjeDB2MAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUXNCJK3/dtCIc\n" +
+        "xb+zlA/JINlvs/MwHwYDVR0jBBgwFoAUuXzV2d+nTAOu/Q4nWzGVbMfzdeEwJwYD\n" +
+        "VR0lBCAwHgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAzANBgkqhkiG9w0B\n" +
+        "AQQFAAOBgQB2qIDUxA2caMPpGtUACZAPRUtrGssCINIfItETXJZCx/cRuZ5sP4D9\n" +
+        "N1acoNDn0hCULe3lhXAeTC9NZ97680yJzregQMV5wATjo1FGsKY30Ma+sc/nfzQW\n" +
+        "+h/7RhYtoG0OTsiaDCvyhI6swkNJzSzrAccPY4+ZgU8HiDLzZTmM3Q==\n" +
+        "-----END CERTIFICATE-----";
+
+    // Private key in the format of PKCS#8, key size is 512 bits.
+    static String targetPrivateKey =
+        "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAtz2+PTkj3zg9hh0l\n" +
+        "xQhcdRiRGX6hvWVH+8biIv62uXS4zxgGqGOUBdkDmvFZzq4kAlw38lx8bLkZxDqJ\n" +
+        "sS+xFQIDAQABAkByx/5Oo2hQ/w2q4L8z+NTRlJ3vdl8iIDtC/4XPnfYfnGptnpG6\n" +
+        "ZThQRvbMZiai0xHQPQMszvAHjZVme1eDl3EBAiEA3aKJHynPVCEJhpfCLWuMwX5J\n" +
+        "1LntwJO7NTOyU5m8rPECIQDTpzn5X44r2rzWBDna/Sx7HW9IWCxNgUD2Eyi2nA7W\n" +
+        "ZQIgJerEorw4aCAuzQPxiGu57PB6GRamAihEAtoRTBQlH0ECIQDN08FgTtnesgCU\n" +
+        "DFYLLcw1CiHvc7fZw4neBDHCrC8NtQIgA8TOUkGnpCZlQ0KaI8KfKWI+vxFcgFnH\n" +
+        "3fnqsTgaUs4=";
+
+    static char passphrase[] = "passphrase".toCharArray();
+
+    /*
+     * Is the server ready to serve?
+     */
+    volatile static boolean serverReady = false;
+
+    /*
+     * Turn on SSL debugging?
+     */
+    static boolean debug = false;
+
+    /*
+     * Define the server side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doServerSide() throws Exception {
+        SSLContext context = generateSSLContext(null, targetCertStr,
+                                            targetPrivateKey);
+        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+        SSLServerSocket sslServerSocket =
+            (SSLServerSocket)sslssf.createServerSocket(serverPort);
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for his connect.
+         */
+        serverReady = true;
+
+        SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
+        sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslIS.read();
+        sslOS.write('A');
+        sslOS.flush();
+
+        sslSocket.close();
+    }
+
+    /*
+     * Define the client side of the test.
+     *
+     * If the server prematurely exits, serverReady will be set to true
+     * to avoid infinite hangs.
+     */
+    void doClientSide() throws Exception {
+
+        /*
+         * Wait for server to get started.
+         */
+        while (!serverReady) {
+            Thread.sleep(50);
+        }
+
+        SSLContext context = generateSSLContext(trustedCertStr, null, null);
+        SSLSocketFactory sslsf = context.getSocketFactory();
+
+        SSLSocket sslSocket =
+            (SSLSocket)sslsf.createSocket("localhost", serverPort);
+
+        // enable TLSv1.2 only
+        sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
+
+        // enable a block cipher
+        sslSocket.setEnabledCipherSuites(new String[] {cipherSuite});
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write('B');
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * The remainder is just support stuff
+     */
+    private static String tmAlgorithm;        // trust manager
+    private static String cipherSuite;        // cipher suite
+
+    private static void parseArguments(String[] args) {
+        tmAlgorithm = args[0];
+        cipherSuite = args[1];
+    }
+
+    private static SSLContext generateSSLContext(String trustedCertStr,
+            String keyCertStr, String keySpecStr) throws Exception {
+
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trused cert
+        Certificate trusedCert = null;
+        ByteArrayInputStream is = null;
+        if (trustedCertStr != null) {
+            is = new ByteArrayInputStream(trustedCertStr.getBytes());
+            trusedCert = cf.generateCertificate(is);
+            is.close();
+
+            ks.setCertificateEntry("RSA Export Signer", trusedCert);
+        }
+
+        if (keyCertStr != null) {
+            // generate the private key.
+            PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+                                new BASE64Decoder().decodeBuffer(keySpecStr));
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            RSAPrivateKey priKey =
+                    (RSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+            // generate certificate chain
+            is = new ByteArrayInputStream(keyCertStr.getBytes());
+            Certificate keyCert = cf.generateCertificate(is);
+            is.close();
+
+            Certificate[] chain = null;
+            if (trusedCert != null) {
+                chain = new Certificate[2];
+                chain[0] = keyCert;
+                chain[1] = trusedCert;
+            } else {
+                chain = new Certificate[1];
+                chain[0] = keyCert;
+            }
+
+            // import the key entry.
+            ks.setKeyEntry("Whatever", priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
+        tmf.init(ks);
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        if (keyCertStr != null && !keyCertStr.isEmpty()) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+            kmf.init(ks, passphrase);
+
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+            ks = null;
+        } else {
+            ctx.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return ctx;
+    }
+
+
+    // use any free port by default
+    volatile int serverPort = 0;
+
+    volatile Exception serverException = null;
+    volatile Exception clientException = null;
+
+    public static void main(String[] args) throws Exception {
+        // reset the security property to make sure that the algorithms
+        // and keys used in this test are not disabled.
+        Security.setProperty("jdk.certpath.disabledAlgorithms", "MD2");
+
+        if (debug) {
+            System.setProperty("javax.net.debug", "all");
+        }
+
+        /*
+         * Get the customized arguments.
+         */
+        parseArguments(args);
+
+        /*
+         * Start the tests.
+         */
+        new ShortRSAKeyGCM();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    ShortRSAKeyGCM() throws Exception {
+        try {
+            if (separateServerThread) {
+                startServer(true);
+                startClient(false);
+            } else {
+                startClient(true);
+                startServer(false);
+            }
+        } catch (Exception e) {
+            // swallow for now.  Show later
+        }
+
+        /*
+         * Wait for other side to close down.
+         */
+        if (separateServerThread) {
+            serverThread.join();
+        } else {
+            clientThread.join();
+        }
+
+        /*
+         * When we get here, the test is pretty much over.
+         * Which side threw the error?
+         */
+        Exception local;
+        Exception remote;
+        String whichRemote;
+
+        if (separateServerThread) {
+            remote = serverException;
+            local = clientException;
+            whichRemote = "server";
+        } else {
+            remote = clientException;
+            local = serverException;
+            whichRemote = "client";
+        }
+
+        /*
+         * If both failed, return the curthread's exception, but also
+         * print the remote side Exception
+         */
+        if ((local != null) && (remote != null)) {
+            System.out.println(whichRemote + " also threw:");
+            remote.printStackTrace();
+            System.out.println();
+            throw local;
+        }
+
+        if (remote != null) {
+            throw remote;
+        }
+
+        if (local != null) {
+            throw local;
+        }
+    }
+
+    void startServer(boolean newThread) throws Exception {
+        if (newThread) {
+            serverThread = new Thread() {
+                public void run() {
+                    try {
+                        doServerSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our server thread just died.
+                         *
+                         * Release the client, if not active already...
+                         */
+                        System.err.println("Server died..." + e);
+                        serverReady = true;
+                        serverException = e;
+                    }
+                }
+            };
+            serverThread.start();
+        } else {
+            try {
+                doServerSide();
+            } catch (Exception e) {
+                serverException = e;
+            } finally {
+                serverReady = true;
+            }
+        }
+    }
+
+    void startClient(boolean newThread) throws Exception {
+        if (newThread) {
+            clientThread = new Thread() {
+                public void run() {
+                    try {
+                        doClientSide();
+                    } catch (Exception e) {
+                        /*
+                         * Our client thread just died.
+                         */
+                        System.err.println("Client died..." + e);
+                        clientException = e;
+                    }
+                }
+            };
+            clientThread.start();
+        } else {
+            try {
+                doClientSide();
+            } catch (Exception e) {
+                clientException = e;
+            }
+        }
+    }
+}
--- a/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/test/sun/security/ssl/sanity/ciphersuites/CipherSuitesInOrder.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, 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
@@ -21,13 +21,15 @@
  * questions.
  */
 
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
 /*
  * @test
  * @bug 7174244
  * @summary NPE in Krb5ProxyImpl.getServerKeys()
- *
- *     SunJSSE does not support dynamic system properties, no way to re-use
- *     system properties in samevm/agentvm mode.
  * @run main/othervm CipherSuitesInOrder
  */
 
@@ -72,6 +74,22 @@
         "SSL_RSA_WITH_RC4_128_SHA",
         "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
         "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+
+        "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+        "TLS_RSA_WITH_AES_256_GCM_SHA384",
+        "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+        "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+        "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+        "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
+        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+        "TLS_RSA_WITH_AES_128_GCM_SHA256",
+        "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+        "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+        "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+        "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+
         "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
         "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
         "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
@@ -83,6 +101,9 @@
 
         "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
 
+        "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
+        "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
+
         "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
         "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
         "TLS_DH_anon_WITH_AES_256_CBC_SHA",
--- a/test/sun/security/ssl/sanity/interop/CipherTest.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/test/sun/security/ssl/sanity/interop/CipherTest.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, 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
@@ -148,6 +148,25 @@
             CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256",     0x0303, 0xFFFF),
             CS_17("TLS_RSA_WITH_NULL_SHA256",                0x0303, 0xFFFF),
 
+            CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),
+            CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),
+            CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",   0x0303, 0xFFFF),
+            CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384",         0x0303, 0xFFFF),
+            CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",  0x0303, 0xFFFF),
+            CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",    0x0303, 0xFFFF),
+            CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+            CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+
+            CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",   0x0303, 0xFFFF),
+            CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256",         0x0303, 0xFFFF),
+            CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",  0x0303, 0xFFFF),
+            CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",    0x0303, 0xFFFF),
+            CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+            CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+
+            CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384",     0x0303, 0xFFFF),
+            CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256",     0x0303, 0xFFFF),
+
             // cipher suites obsoleted since TLS 1.2
             CS_50("SSL_RSA_WITH_DES_CBC_SHA",                0x0000, 0x0303),
             CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA",            0x0000, 0x0303),
--- a/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java	Tue Apr 16 12:23:16 2013 +0100
+++ b/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java	Tue Apr 16 05:11:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, 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
@@ -21,14 +21,15 @@
  * questions.
  */
 
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
 /*
  * @test
  * @bug 7105780
  * @summary Add SSLSocket client/SSLEngine server to templates directory.
- *
- *     SunJSSE does not support dynamic system properties, no way to re-use
- *     system properties in samevm/agentvm mode.
- *
  * @run main/othervm SSLSocketSSLEngineTemplate
  */