Merge
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index cb07f9a..a3359f0 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -416,3 +416,4 @@
 d99f3f935397fdc65dcb776a97110e8ff5cc519c jdk8u51-b10
 29612174658436601ba833993227ae96117f632c jdk8u51-b11
 f07a9ef02d513435e19fd70abcce2871d1c91342 jdk8u51-b12
+6ef21f3e0946aaab8dc1f4e9cad21dacb97c4f8c jdk8u51-b13
diff --git a/corba/.hgtags b/corba/.hgtags
index 12380e3..3ba7d60 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -414,3 +414,4 @@
 0011162b38bf4dab36c72bf25640c59d7128274a jdk8u51-b10
 4d59046bdb8a05cfb9e07d8e18d44956f700fe29 jdk8u51-b11
 e51a2deadf774452d98b339d65d33c72a466a453 jdk8u51-b12
+4886143e8749caf2ec42a6e77c70a98516e140a3 jdk8u51-b13
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 79f179f..200b9ea 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -628,3 +628,4 @@
 928e1994ad43272f808ca22b9cc1b08a7ce2824f jdk8u51-b10
 1a122beb9dc6881850ef1d1250f40a83709b8b72 jdk8u51-b11
 05c80f1060f0c0d5720de9eadd09162af1168eab jdk8u51-b12
+07e103f3f43886a3b47945e5295eb5accad505de jdk8u51-b13
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index 41338f3..1a0b833 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -416,3 +416,4 @@
 7aacd8c67160af67f7c9d81974d021eeb229929e jdk8u51-b10
 04005432fba4982e5c073be55b917f8a11c838f0 jdk8u51-b11
 966c04d5702882603a02f5ba4a4e5d19d47960f6 jdk8u51-b12
+3f5353208a226a31d9ad86018a17fe5f3b102d4b jdk8u51-b13
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index d4a8013..ad1a4e3 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -414,3 +414,4 @@
 783b917616ab6977f9b3157667d1493636ba66d1 jdk8u51-b10
 5a69995912aae8bd61758e95a3b5edac167b6acc jdk8u51-b11
 1a855f69de645c4bd485d5fb6d9a524994278a16 jdk8u51-b12
+880b67345f557d5613071d09c1cf234a7e1b8759 jdk8u51-b13
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 19b38eb..93f6ad9 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -419,3 +419,4 @@
 dcc75a75d3a30270fbf52d0d0b0504319882e419 jdk8u51-b10
 3ed614d4eee7c3225d48ed7c90622dd888cd143e jdk8u51-b11
 0010682d9a2b81daf7c08239161f7c2a91977299 jdk8u51-b12
+217fa7205549d196c60f814bf3fc9795d756f493 jdk8u51-b13
diff --git a/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java b/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java
index d4cd740..f8a3eaa 100644
--- a/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java
+++ b/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java
@@ -38,7 +38,17 @@
  * under section 6.5. It needs to be constructed w/ an initialized
  * cipher object, and initial counter block(ICB). Given an input X
  * of arbitrary length, it processes and returns an output which has
- * the same length as X.
+ * the same length as X. The invariants of this class are:
+ *
+ * (1) The length of intialCounterBlk (and also of its clones, e.g.,
+ * fields counter and counterSave) is equal to AES_BLOCK_SIZE.
+ *
+ * (2) After construction, the field counter never becomes null, it
+ * always contains a byte array of length AES_BLOCK_SIZE.
+ *
+ * If any invariant is broken, failures can occur because the
+ * AESCrypt.encryptBlock method can be intrinsified on the HotSpot VM
+ * (see JDK-8067648 for details).
  *
  * <p>This function is used in the implementation of GCM mode.
  *
@@ -59,6 +69,10 @@
     // NOTE: cipher should already be initialized
     GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) {
         this.aes = cipher;
+        if (initialCounterBlk.length != AES_BLOCK_SIZE) {
+            throw new RuntimeException("length of initial counter block (" + initialCounterBlk.length +
+                                       ") not equal to AES_BLOCK_SIZE (" + AES_BLOCK_SIZE + ")");
+        }
         this.icb = initialCounterBlk;
         this.counter = icb.clone();
     }
@@ -137,6 +151,8 @@
      * Restores the content of this object to the previous saved one.
      */
     void restore() {
-        this.counter = this.counterSave;
+        if (this.counterSave != null) {
+            this.counter = this.counterSave;
+        }
     }
 }
diff --git a/jdk/src/share/classes/javax/crypto/CipherInputStream.java b/jdk/src/share/classes/javax/crypto/CipherInputStream.java
index d777ca0..ded3b24 100644
--- a/jdk/src/share/classes/javax/crypto/CipherInputStream.java
+++ b/jdk/src/share/classes/javax/crypto/CipherInputStream.java
@@ -25,7 +25,11 @@
 
 package javax.crypto;
 
-import java.io.*;
+import java.io.InputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
 
 /**
  * A CipherInputStream is composed of an InputStream and a Cipher so
@@ -88,8 +92,6 @@
     private int ofinish = 0;
     // stream status
     private boolean closed = false;
-    // The stream has been read from.  False if the stream has never been read.
-    private boolean read = false;
 
     /**
      * private convenience function.
@@ -101,11 +103,15 @@
      * return (ofinish-ostart) (we have this many bytes for you)
      * return 0 (no data now, but could have more later)
      * return -1 (absolutely no more data)
+     *
+     * Note:  Exceptions are only thrown after the stream is completely read.
+     * For AEAD ciphers a read() of any length will internally cause the
+     * whole stream to be read fully and verify the authentication tag before
+     * returning decrypted data or exceptions.
      */
     private int getMoreData() throws IOException {
         if (done) return -1;
         int readin = input.read(ibuffer);
-        read = true;
         if (readin == -1) {
             done = true;
             try {
@@ -308,17 +314,16 @@
 
         closed = true;
         input.close();
-        try {
-            // throw away the unprocessed data
-            if (!done) {
+
+        // Throw away the unprocessed data and throw no crypto exceptions.
+        // AEAD ciphers are fully readed before closing.  Any authentication
+        // exceptions would occur while reading.
+        if (!done) {
+            try {
                 cipher.doFinal();
             }
-        }
-        catch (BadPaddingException | IllegalBlockSizeException ex) {
-            /* If no data has been read from the stream to be en/decrypted,
-               we supress any exceptions, and close quietly. */
-            if (read) {
-                throw new IOException(ex);
+            catch (BadPaddingException | IllegalBlockSizeException ex) {
+                // Catch exceptions as the rest of the stream is unused.
             }
         }
         ostart = 0;
diff --git a/jdk/test/javax/crypto/Cipher/CipherInputStreamExceptions.java b/jdk/test/javax/crypto/Cipher/CipherInputStreamExceptions.java
new file mode 100644
index 0000000..783967a
--- /dev/null
+++ b/jdk/test/javax/crypto/Cipher/CipherInputStreamExceptions.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2015, 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 8064546
+ * @summary Throw exceptions during reading but not closing of a
+ * CipherInputStream:
+ * - Make sure authenticated algorithms continue to throwing exceptions
+ *   when the authentication tag fails verification.
+ * - Make sure other algorithms do not throw exceptions when the stream
+ *   calls close() and only throw when read() errors.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.Exception;
+import java.lang.RuntimeException;
+import java.lang.Throwable;
+import java.security.AlgorithmParameters;
+import javax.crypto.AEADBadTagException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.crypto.spec.GCMParameterSpec;
+
+public class CipherInputStreamExceptions {
+
+    static SecretKeySpec key = new SecretKeySpec(new byte[16], "AES");
+    static GCMParameterSpec gcmspec = new GCMParameterSpec(128, new byte[16]);
+    static IvParameterSpec iv = new IvParameterSpec(new byte[16]);
+    static boolean failure = false;
+
+    /* Full read stream, check that getMoreData() is throwing an exception
+     * This test
+     *   1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
+     *   2) Changes the last byte to invalidate the authetication tag.
+     *   3) Fully reads CipherInputStream to decrypt the message and closes
+     */
+
+    static void gcm_AEADBadTag() throws Exception {
+        Cipher c;
+        byte[] read = new byte[200];
+
+        System.out.println("Running gcm_AEADBadTag");
+
+        // Encrypt 100 bytes with AES/GCM/PKCS5Padding
+        byte[] ct = encryptedText("GCM", 100);
+        // Corrupt the encrypted message
+        ct = corruptGCM(ct);
+        // Create stream for decryption
+        CipherInputStream in = getStream("GCM", ct);
+
+        try {
+            int size = in.read(read);
+            throw new RuntimeException("Fail: CipherInputStream.read() " +
+                    "returned " + size + " and didn't throw an exception.");
+        } catch (IOException e) {
+            Throwable ec = e.getCause();
+            if (ec instanceof AEADBadTagException) {
+                System.out.println("  Pass.");
+            } else {
+                System.out.println("  Fail: " + ec.getMessage());
+                throw new RuntimeException(ec);
+            }
+        } finally {
+            in.close();
+        }
+    }
+
+    /* Short read stream,
+     * This test
+     *   1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
+     *   2) Reads 100 bytes from stream to decrypt the message and closes
+     *   3) Make sure no value is returned by read()
+     *   4) Make sure no exception is thrown
+     */
+
+    static void gcm_shortReadAEAD() throws Exception {
+        Cipher c;
+        byte[] read = new byte[100];
+
+        System.out.println("Running gcm_shortReadAEAD");
+
+        byte[] pt = new byte[600];
+        pt[0] = 1;
+        // Encrypt provided 600 bytes with AES/GCM/PKCS5Padding
+        byte[] ct = encryptedText("GCM", pt);
+        // Create stream for decryption
+        CipherInputStream in = getStream("GCM", ct);
+
+        int size = 0;
+        try {
+            size = in.read(read);
+            in.close();
+            if (read.length != 100) {
+                throw new RuntimeException("Fail: read size = " + read.length +
+                        "should be 100.");
+            }
+            if (read[0] != 1) {
+                throw new RuntimeException("Fail: The decrypted text does " +
+                        "not match the plaintext: '" + read[0] +"'");
+            }
+        } catch (IOException e) {
+            System.out.println("  Fail: " + e.getMessage());
+            throw new RuntimeException(e.getCause());
+        }
+        System.out.println("  Pass.");
+    }
+
+    /*
+     * Verify doFinal() exception is suppressed when input stream is not
+     * read before it is closed.
+     * This test:
+     *   1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
+     *   2) Changes the last byte to invalidate the authetication tag.
+     *   3) Opens a CipherInputStream and the closes it. Never reads from it.
+     *
+     * There should be no exception thrown.
+     */
+    static void gcm_suppressUnreadCorrupt() throws Exception {
+        Cipher c;
+        byte[] read = new byte[200];
+
+        System.out.println("Running supressUnreadCorrupt test");
+
+        // Encrypt 100 bytes with AES/GCM/PKCS5Padding
+        byte[] ct = encryptedText("GCM", 100);
+        // Corrupt the encrypted message
+        ct = corruptGCM(ct);
+        // Create stream for decryption
+        CipherInputStream in = getStream("GCM", ct);
+
+        try {
+            in.close();
+            System.out.println("  Pass.");
+        } catch (IOException e) {
+            System.out.println("  Fail: " + e.getMessage());
+            throw new RuntimeException(e.getCause());
+        }
+    }
+
+    /*
+     * Verify noexception thrown when 1 byte is read from a GCM stream
+     * and then closed
+     * This test:
+     *   1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
+     *   2) Read one byte from the stream, expect no exception thrown.
+     *   4) Close stream,expect no exception thrown.
+     */
+    static void gcm_oneReadByte() throws Exception {
+
+        System.out.println("Running gcm_oneReadByte test");
+
+        // Encrypt 100 bytes with AES/GCM/PKCS5Padding
+        byte[] ct = encryptedText("GCM", 100);
+        // Create stream for decryption
+        CipherInputStream in = getStream("GCM", ct);
+
+        try {
+            in.read();
+            System.out.println("  Pass.");
+        } catch (Exception e) {
+            System.out.println("  Fail: " + e.getMessage());
+            throw new RuntimeException(e.getCause());
+        }
+    }
+
+    /*
+     * Verify exception thrown when 1 byte is read from a corrupted GCM stream
+     * and then closed
+     * This test:
+     *   1) Encrypt 100 bytes with AES/GCM/PKCS5Padding
+     *   2) Changes the last byte to invalidate the authetication tag.
+     *   3) Read one byte from the stream, expect exception thrown.
+     *   4) Close stream,expect no exception thrown.
+     */
+    static void gcm_oneReadByteCorrupt() throws Exception {
+
+        System.out.println("Running gcm_oneReadByteCorrupt test");
+
+        // Encrypt 100 bytes with AES/GCM/PKCS5Padding
+        byte[] ct = encryptedText("GCM", 100);
+        // Corrupt the encrypted message
+        ct = corruptGCM(ct);
+        // Create stream for decryption
+        CipherInputStream in = getStream("GCM", ct);
+
+        try {
+            in.read();
+            System.out.println("  Fail. No exception thrown.");
+        } catch (IOException e) {
+            Throwable ec = e.getCause();
+            if (ec instanceof AEADBadTagException) {
+                System.out.println("  Pass.");
+            } else {
+                System.out.println("  Fail: " + ec.getMessage());
+                throw new RuntimeException(ec);
+            }
+        }
+    }
+
+    /* Check that close() does not throw an exception with full message in
+     * CipherInputStream's ibuffer.
+     * This test:
+     *   1) Encrypts a 97 byte message with AES/CBC/PKCS5Padding
+     *   2) Create a stream that sends 96 bytes.
+     *   3) Read stream once,
+     *   4) Close and expect no exception
+     */
+
+    static void cbc_shortStream() throws Exception {
+        Cipher c;
+        AlgorithmParameters params;
+        byte[] read = new byte[200];
+
+        System.out.println("Running cbc_shortStream");
+
+        // Encrypt 97 byte with AES/CBC/PKCS5Padding
+        byte[] ct = encryptedText("CBC", 97);
+        // Create stream with only 96 bytes of encrypted data
+        CipherInputStream in = getStream("CBC", ct, 96);
+
+        try {
+            int size = in.read(read);
+            in.close();
+            if (size != 80) {
+                throw new RuntimeException("Fail: CipherInputStream.read() " +
+                        "returned " + size + ". Should have been 80");
+            }
+            System.out.println("  Pass.");
+        } catch (IOException e) {
+            System.out.println("  Fail:  " + e.getMessage());
+            throw new RuntimeException(e.getCause());
+        }
+    }
+
+    /* Check that close() does not throw an exception when the whole message is
+     * inside the internal buffer (ibuffer) in CipherInputStream and we read
+     * one byte and close the stream.
+     * This test:
+     *   1) Encrypts a 400 byte message with AES/CBC/PKCS5Padding
+     *   2) Read one byte from the stream
+     *   3) Close and expect no exception
+     */
+
+    static void cbc_shortRead400() throws Exception {
+        System.out.println("Running cbc_shortRead400");
+
+        // Encrypt 400 byte with AES/CBC/PKCS5Padding
+        byte[] ct = encryptedText("CBC", 400);
+        // Create stream with encrypted data
+        CipherInputStream in = getStream("CBC", ct);
+
+        try {
+            in.read();
+            in.close();
+            System.out.println("  Pass.");
+        } catch (IOException e) {
+            System.out.println("  Fail:  " + e.getMessage());
+            throw new RuntimeException(e.getCause());
+        }
+    }
+
+    /* Check that close() does not throw an exception when the  inside the
+     * internal buffer (ibuffer) in CipherInputStream does not contain the
+     * whole message.
+     * This test:
+     *   1) Encrypts a 600 byte message with AES/CBC/PKCS5Padding
+     *   2) Read one byte from the stream
+     *   3) Close and expect no exception
+     */
+
+    static void cbc_shortRead600() throws Exception {
+        System.out.println("Running cbc_shortRead600");
+
+        // Encrypt 600 byte with AES/CBC/PKCS5Padding
+        byte[] ct = encryptedText("CBC", 600);
+        // Create stream with encrypted data
+        CipherInputStream in = getStream("CBC", ct);
+
+        try {
+            in.read();
+            in.close();
+            System.out.println("  Pass.");
+        } catch (IOException e) {
+            System.out.println("  Fail:  " + e.getMessage());
+            throw new RuntimeException(e.getCause());
+        }
+    }
+
+    /* Check that exception is thrown when message is fully read
+     * This test:
+     *   1) Encrypts a 96 byte message with AES/CBC/PKCS5Padding
+     *   2) Create a stream that sends 95 bytes.
+     *   3) Read stream to the end
+     *   4) Expect IllegalBlockSizeException thrown
+     */
+
+    static void cbc_readAllIllegalBlockSize() throws Exception {
+        byte[] read = new byte[200];
+
+        System.out.println("Running cbc_readAllIllegalBlockSize test");
+
+        // Encrypt 96 byte with AES/CBC/PKCS5Padding
+        byte[] ct = encryptedText("CBC", 96);
+        // Create a stream with only 95 bytes of encrypted data
+        CipherInputStream in = getStream("CBC", ct, 95);
+
+        try {
+            int s, size = 0;
+            while ((s = in.read(read)) != -1) {
+                size += s;
+            }
+            throw new RuntimeException("Fail: No IllegalBlockSizeException. " +
+                    "CipherInputStream.read() returned " + size);
+
+        } catch (IOException e) {
+            Throwable ec = e.getCause();
+            if (ec instanceof IllegalBlockSizeException) {
+                System.out.println("  Pass.");
+            } else {
+                System.out.println("  Fail: " + ec.getMessage());
+                throw new RuntimeException(ec);
+            }
+        }
+    }
+
+    /* Generic method to create encrypted text */
+    static byte[] encryptedText(String mode, int length) throws Exception{
+        return encryptedText(mode, new byte[length]);
+    }
+
+    /* Generic method to create encrypted text */
+    static byte[] encryptedText(String mode, byte[] pt) throws Exception{
+        Cipher c;
+        if (mode.compareTo("GCM") == 0) {
+            c = Cipher.getInstance("AES/GCM/PKCS5Padding", "SunJCE");
+            c.init(Cipher.ENCRYPT_MODE, key, gcmspec);
+        } else if (mode.compareTo("CBC") == 0) {
+            c = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
+            c.init(Cipher.ENCRYPT_MODE, key, iv);
+        } else {
+            return null;
+        }
+
+        return c.doFinal(pt);
+    }
+
+    /* Generic method to get a properly setup CipherInputStream */
+    static CipherInputStream getStream(String mode, byte[] ct) throws Exception {
+        return getStream(mode, ct, ct.length);
+    }
+
+    /* Generic method to get a properly setup CipherInputStream */
+    static CipherInputStream getStream(String mode, byte[] ct, int length)
+            throws Exception {
+        Cipher c;
+
+        if (mode.compareTo("GCM") == 0) {
+            c = Cipher.getInstance("AES/GCM/PKCS5Padding", "SunJCE");
+            c.init(Cipher.DECRYPT_MODE, key, gcmspec);
+        } else if (mode.compareTo("CBC") == 0) {
+            c = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
+            c.init(Cipher.DECRYPT_MODE, key, iv);
+        } else {
+            return null;
+        }
+
+        return new CipherInputStream(new ByteArrayInputStream(ct, 0, length), c);
+
+    }
+
+    /* Generic method for corrupting a GCM message.  Change the last
+     * byte on of the authentication tag
+     */
+    static byte[] corruptGCM(byte[] ct) {
+        ct[ct.length - 1] = (byte) (ct[ct.length - 1] + 1);
+        return ct;
+    }
+
+    public static void main(String[] args) throws Exception {
+        gcm_AEADBadTag();
+        gcm_shortReadAEAD();
+        gcm_suppressUnreadCorrupt();
+        gcm_oneReadByte();
+        gcm_oneReadByteCorrupt();
+        cbc_shortStream();
+        cbc_shortRead400();
+        cbc_shortRead600();
+        cbc_readAllIllegalBlockSize();
+    }
+}
diff --git a/langtools/.hgtags b/langtools/.hgtags
index 6959516..fd4e8f8 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -414,3 +414,4 @@
 417f734de62d74c69e3a8465340bfb3aca60151a jdk8u51-b10
 8ac1243890d4f427a32320b81ae1be38f81f0c62 jdk8u51-b11
 f65c2fc549b5e9184da67e3a4f81260c27a88010 jdk8u51-b12
+3836d67a94a92befedd97064358270c6f0760e5c jdk8u51-b13
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index e266495..3a9d234 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -402,3 +402,4 @@
 1480e27e4af65e809c1a5cc0310616c2c68392f2 jdk8u51-b10
 6e95b9bb2f67d4a77d28e5aa3c07281fc8424823 jdk8u51-b11
 bf2fe867628bf323262377f8312c85f440a9b246 jdk8u51-b12
+1ecbb6d582a6ccf9e0f6e359a925155c8c580bac jdk8u51-b13