changeset 10736:e7e36535d70e

8067648: JVM crashes reproducible with GCM cipher suites in GCTR doFinal Summary: Change restore mechanism in GCTR.java to avoid setting counter to null; added length check to constructor Reviewed-by: jrose, kvn, ascarpino
author zmajo
date Tue, 21 Apr 2015 09:56:55 +0200
parents 801874e394a7
children db118766355e
files src/share/classes/com/sun/crypto/provider/GCTR.java
diffstat 1 files changed, 18 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/GCTR.java	Wed Apr 15 14:45:20 2015 -0700
+++ b/src/share/classes/com/sun/crypto/provider/GCTR.java	Tue Apr 21 09:56:55 2015 +0200
@@ -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;
+        }
     }
 }