JDK-8220165 : Encryption using GCM results in RuntimeException: input length out of bound
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.crypto
  • Affected Version: 11,12,13
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86_64
  • Submitted: 2019-03-04
  • Updated: 2020-08-02
  • Resolved: 2019-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 12 JDK 13 JDK 8 Other
11.0.2Fixed 12.0.2Fixed 13 b12Fixed 8u261Fixed openjdk8u272Fixed
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz, x86_64
Ubuntu 16.04.6 LTS
Openjdk-13 (https://jdk.java.net/13/)

A DESCRIPTION OF THE PROBLEM :
Encrypting using the GCM algorithm causes the com.sun.crypto.provider.GHASH.ghashRangeCheck function to raise "input length out of bound"�� exception, even though the input length is not out of bound. In particular, when running the same code with the same parameters in openjdk-11 everything works, and no exception is raised.

REGRESSION : Last worked in version 11.0.1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.	Create an instance of javax.crypto.Cipher with the parameter "AES/GCM/NoPadding"
2.	Init the cipher with nonce (random byte-array of size 12)
3.	Allocate byte-array for the input with size 100001
4.	Call cipher.doFinal(inputArray)

From some playing around with the sizes of the inputArray, it looks like the problem starts when the size of the InputArray is greater than 2^16 (2^16 + 1 for instance). But some sizes seem to work though, for example 100000, 1000000, 10000000 etc.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The cipher encrypts the inputArray successfully.
ACTUAL -
Getting exception in the com.sun.crypto.provider.GHASH.ghashRangeCheck function. In particular, the input length is not as the size of the inputArray (which is 100001), and I'm not sure where the number 90705 comes from.

Exception in thread "main" java.lang.RuntimeException: input length out of bound: 100000 > 90705
        at java.base/com.sun.crypto.provider.GHASH.ghashRangeCheck(GHASH.java:209)
        at java.base/com.sun.crypto.provider.GHASH.update(GHASH.java:197)
        at java.base/com.sun.crypto.provider.GaloisCounterMode.doLastBlock(GaloisCounterMode.java:424)
        at java.base/com.sun.crypto.provider.GaloisCounterMode.encryptFinal(GaloisCounterMode.java:497)
        at java.base/com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1118)
        at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1053)
        at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
        at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
        at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2208)
        at EncBug.bugGCM(EncBug.java:35)
        at EncBug.main(EncBug.java:40)

---------- BEGIN SOURCE ----------
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Random;

public class EncBug {
    public static byte[] bugGCM() throws Exception {
        // AES-GCM parameters
        int GCM_NONCE_LENGTH = 12; // in bytes
        int GCM_TAG_LENGTH = 16; // in bytes

        int inputSize = 100001;
        //int inputSize = 65536 + 1; // 2^16 == 65536

        // init input
        byte[] inputArray = new byte[inputSize];
        for (int i=0; i < inputArray.length; i++) {
            inputArray[i] = (byte)i;
        }

        // init cipher
        Cipher cipher;
        cipher = Cipher.getInstance("AES/GCM/NoPadding");

        // init nonce
        final byte[] nonce = new byte[GCM_NONCE_LENGTH];
        Random random = new Random();
        random.nextBytes(nonce);
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, nonce);

        byte[] key_code = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
        SecretKey key = new SecretKeySpec(key_code, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key, spec);
        byte[] outputArray = cipher.doFinal(inputArray);
        return outputArray;
    }

    public static void main(String[] args) throws Exception {
        bugGCM();
    }
}
---------- END SOURCE ----------

FREQUENCY : always



Comments
Fix Request (8u) Same reason as for 11u. Patch applies with minor problems in test code. 8u RFR (acked by Severin): https://mail.openjdk.java.net/pipermail/jdk8u-dev/2020-July/012307.html
31-07-2020

Verified it by running test com/sun/crypto/provider/Cipher/AEAD/GCMLargeDataKAT.java with jdk13+27.
01-07-2019

Fix Request This fixes the failure introduced by JDK-8201633, which is already backported to both 12u and 11u. Patch applies cleanly to 12u and 11u. New regression tests fails without the patch in both 12u and 11u, and passes with the fix. jdk_security test suite passes in 11u and 12u after the patch too.
08-03-2019

The larger data sizes about 64k have a problem with data not on a block boundary because of the change. It also shows we lack tests for GCM with large data sizes
06-03-2019

To reproduce the issue, run the attached test case: JDK 11 - Pass JDK 12 - Pass JDK 13-ea b07 - Pass JDK 13-ea b08 - Fail JDK 13-ea b10 - Fail Output: Exception in thread "main" java.lang.RuntimeException: input length out of bound: 100000 > 90705 at java.base/com.sun.crypto.provider.GHASH.ghashRangeCheck(GHASH.java:209) at java.base/com.sun.crypto.provider.GHASH.update(GHASH.java:197) at java.base/com.sun.crypto.provider.GaloisCounterMode.doLastBlock(GaloisCounterMode.java:424) at java.base/com.sun.crypto.provider.GaloisCounterMode.encryptFinal(GaloisCounterMode.java:497) at java.base/com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1118) at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1053) at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853) at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446) at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2208) at JI9059629.bugGCM(JI9059629.java:36) at JI9059629.main(JI9059629.java:41) JDK-8201633 may be related as that was included in b08.
05-03-2019