8067648: JVM crashes reproducible with GCM cipher suites in GCTR doFinal
authorzmajo
Wed, 15 Apr 2015 09:37:51 +0200
changeset 30344 72127fbf9974
parent 30339 ebd762f09224
child 30345 9c3d245dd8cc
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
jdk/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java	Fri Apr 03 11:41:26 2015 -0700
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java	Wed Apr 15 09:37:51 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;
+        }
     }
 }