Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8314045

ArithmeticException in GaloisCounterMode

XMLWordPrintable

    • b11
    • Verified

        My colleage Ioana Nedelcu discovered the following issue.

        In JDK 17 and newer, GaloisCounterMode executes a check that fails with an ArithmeticException if the input data is too short [1], instead of throwing a AEADBadTagException.

        [1] https://github.com/openjdk/jdk/blob/0eb0997ae4f81314b764241e69dae5c698dbb6c6/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java#L1575
        [2] https://github.com/openjdk/jdk/blob/0eb0997ae4f81314b764241e69dae5c698dbb6c6/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java#L1603C27-L1605

        The change was detected by running this test on a recent JDK version: https://github.com/google/tink/blob/43d5698a442b7ca6bcc5c0661af5939559a03dc8/java_src/src/test/java/com/google/crypto/tink/subtle/AesGcmHkdfStreamingTest.java#L276

        The following repro shows the same crash:

        ```
        import javax.crypto.Cipher;
        import javax.crypto.spec.GCMParameterSpec;
        import javax.crypto.spec.SecretKeySpec;
        import java.nio.ByteBuffer;

        public class Test {
            public static void main(String[] args) throws Exception {
                SecretKeySpec keySpec = new SecretKeySpec(new byte[]{88, 26, 43, -100, -24, -29, -70, 10, 34, -85, 52, 101, 45, -68, -105, -123}, "AES");
                GCMParameterSpec params = new GCMParameterSpec(8 * 16, new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
                Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
                cipher.init(Cipher.DECRYPT_MODE, keySpec, params);
                cipher.doFinal(ByteBuffer.allocate(0), ByteBuffer.allocate(0));
            }
        }
        ```

        $ java -fullversion
        openjdk full version "16-ea+34-2216"
        $ java Test
        Exception in thread "main" javax.crypto.AEADBadTagException: Input too short - need tag
                at java.base/com.sun.crypto.provider.GaloisCounterMode.decryptFinal(GaloisCounterMode.java:738)
                at java.base/com.sun.crypto.provider.CipherCore.finalNoPadding(CipherCore.java:1122)
                at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1059)
                at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:946)
                at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:501)
                at java.base/javax.crypto.CipherSpi.bufferCrypt(CipherSpi.java:799)
                at java.base/javax.crypto.CipherSpi.engineDoFinal(CipherSpi.java:735)
                at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:673)
                at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2500)
                at Test.main(Test.java:18)

        $ java -fullversion
        openjdk full version "17.0.2+8-86"
        $ java Test
        Exception in thread "main" java.lang.ArithmeticException: integer overflow
                at java.base/java.lang.Math.subtractExact(Math.java:924)
                at java.base/com.sun.crypto.provider.GaloisCounterMode.checkDataLength(GaloisCounterMode.java:576)
                at java.base/com.sun.crypto.provider.GaloisCounterMode$GCMDecrypt.doFinal(GaloisCounterMode.java:1433)
                at java.base/com.sun.crypto.provider.GaloisCounterMode.engineDoFinal(GaloisCounterMode.java:447)
                at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2500)
                at Test.main(Test.java:18)

              cushon Liam Miller-Cushon
              cushon Liam Miller-Cushon
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Created:
                Updated:
                Resolved: