changeset 1718:ce758cf960f3

8171252: Improve exception checking 8158517: Minor optimizations to ISO10126PADDING Reviewed-by: ascarpino, mschoene
author igerasim
date Thu, 23 Mar 2017 15:00:29 -0700
parents 2e4da5489155
children a52e30264abb
files src/share/classes/com/sun/crypto/provider/AESCipher.java src/share/classes/com/sun/crypto/provider/AESWrapCipher.java src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java src/share/classes/com/sun/crypto/provider/BlowfishCipher.java src/share/classes/com/sun/crypto/provider/CipherCore.java src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java src/share/classes/com/sun/crypto/provider/ISO10126Padding.java src/share/classes/com/sun/crypto/provider/PBECipherCore.java src/share/classes/com/sun/crypto/provider/PKCS5Padding.java
diffstat 9 files changed, 90 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/AESCipher.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/AESCipher.java	Thu Mar 23 15:00:29 2017 -0700
@@ -28,7 +28,6 @@
 import java.security.*;
 import java.security.spec.*;
 import javax.crypto.*;
-import javax.crypto.spec.*;
 import javax.crypto.BadPaddingException;
 
 /**
@@ -140,7 +139,7 @@
                 throw new InvalidKeyException("Key encoding must not be null");
             } else if (value.length != fixedKeySize) {
                 throw new InvalidKeyException("The key must be " +
-                    fixedKeySize*8 + " bits");
+                    fixedKeySize + " bytes");
             }
         }
     }
@@ -479,7 +478,7 @@
             throw new InvalidKeyException("Invalid AES key length: " +
                                           encoded.length + " bytes");
         }
-        return encoded.length * 8;
+        return CipherCore.multiplyExact(encoded.length, 8);
     }
 
     /**
--- a/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java	Thu Mar 23 15:00:29 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -25,11 +25,9 @@
 
 package com.sun.crypto.provider;
 
-import java.util.Arrays;
 import java.security.*;
 import java.security.spec.*;
 import javax.crypto.*;
-import javax.crypto.spec.*;
 
 /**
  * This class implements the AES KeyWrap algorithm as defined
@@ -156,7 +154,7 @@
         if (decrypting) {
             result = inputLen - 8;
         } else {
-            result = inputLen + 8;
+            result = CipherCore.addExact(inputLen, 8);
         }
         return (result < 0? 0:result);
     }
@@ -378,7 +376,7 @@
             throw new InvalidKeyException("Invalid key length: " +
                                           encoded.length + " bytes");
         }
-        return encoded.length * 8;
+        return CipherCore.multiplyExact(encoded.length, 8);
     }
 
     /**
@@ -404,7 +402,7 @@
             throw new InvalidKeyException("Cannot get an encoding of " +
                                           "the key to be wrapped");
         }
-        byte[] out = new byte[keyVal.length + 8];
+        byte[] out = new byte[CipherCore.addExact(keyVal.length, 8)];
 
         if (keyVal.length == 8) {
             System.arraycopy(IV, 0, out, 0, IV.length);
--- a/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java	Thu Mar 23 15:00:29 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -256,7 +256,7 @@
     // see JCE spec
     protected int engineGetKeySize(Key key) throws InvalidKeyException {
         byte[] encodedKey = getEncodedKey(key);
-        return encodedKey.length << 3;
+        return CipherCore.multiplyExact(encodedKey.length, 8);
     }
 
 }
--- a/src/share/classes/com/sun/crypto/provider/BlowfishCipher.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/BlowfishCipher.java	Thu Mar 23 15:00:29 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -27,9 +27,7 @@
 
 import java.security.*;
 import java.security.spec.*;
-import sun.security.util.*;
 import javax.crypto.*;
-import javax.crypto.spec.*;
 import javax.crypto.BadPaddingException;
 
 /**
@@ -373,7 +371,7 @@
      * @exception InvalidKeyException if <code>key</code> is invalid.
      */
     protected int engineGetKeySize(Key key) throws InvalidKeyException {
-        return (key.getEncoded().length * 8);
+        return CipherCore.multiplyExact(key.getEncoded().length, 8);
     }
 
     /**
--- a/src/share/classes/com/sun/crypto/provider/CipherCore.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java	Thu Mar 23 15:00:29 2017 -0700
@@ -268,7 +268,7 @@
      * @return the required output buffer size (in bytes)
      */
     int getOutputSize(int inputLen) {
-        int totalLen = buffered + inputLen;
+        int totalLen = addExact(buffered, inputLen);
 
         if (padding == null)
             return totalLen;
@@ -277,13 +277,14 @@
             return totalLen;
 
         if (unitBytes != blockSize) {
-            if (totalLen < diffBlocksize)
+            if (totalLen < diffBlocksize) {
                 return diffBlocksize;
-            else
-                return (totalLen + blockSize -
-                        ((totalLen - diffBlocksize) % blockSize));
+            } else {
+                int residue = (totalLen - diffBlocksize) % blockSize;
+                return addExact(totalLen, (blockSize - residue));
+            }
         } else {
-            return totalLen + padding.padLength(totalLen);
+            return addExact(totalLen, padding.padLength(totalLen));
         }
     }
 
@@ -568,7 +569,8 @@
     int update(byte[] input, int inputOffset, int inputLen, byte[] output,
                int outputOffset) throws ShortBufferException {
         // figure out how much can be sent to crypto function
-        int len = buffered + inputLen - minBytes;
+        int len = addExact(buffered, inputLen);
+        len -= minBytes;
         if (padding != null && decrypting) {
             // do not include the padding bytes when decrypting
             len -= blockSize;
@@ -619,8 +621,8 @@
             }
 
             inputLen -= inputConsumed;
-            inputOffset += inputConsumed;
-            outputOffset += len;
+            inputOffset = addExact(inputOffset, inputConsumed);
+            outputOffset = addExact(outputOffset, len);
             buffered -= bufferedConsumed;
             if (buffered > 0) {
                 System.arraycopy(buffer, bufferedConsumed, buffer, 0,
@@ -632,7 +634,7 @@
             System.arraycopy(input, inputOffset, buffer, buffered,
                              inputLen);
         }
-        buffered += inputLen;
+        buffered = addExact(buffered, inputLen);
         return len;
     }
 
@@ -728,7 +730,7 @@
                BadPaddingException {
 
         // calculate the total input length
-        int totalLen = buffered + inputLen;
+        int totalLen = addExact(buffered, inputLen);
         int paddedLen = totalLen;
         int paddingLen = 0;
 
@@ -753,7 +755,7 @@
 
         // if encrypting and padding not null, add padding
         if (!decrypting && padding != null)
-            paddedLen += paddingLen;
+            paddedLen = addExact(paddedLen, paddingLen);
 
         // check output buffer capacity.
         // if we are decrypting with padding applied, we can perform this
@@ -939,4 +941,43 @@
         return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
                                           wrappedKeyType);
     }
+
+    /* Taken from java.lang.Math in OpenJDK  8 */
+
+    /**
+     * Returns the sum of its arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @since 1.8
+     */
+    public static int addExact(int x, int y) {
+        int r = x + y;
+        // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+        if (((x ^ r) & (y ^ r)) < 0) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return r;
+    }
+
+    /**
+     * Returns the product of the arguments,
+     * throwing an exception if the result overflows an {@code int}.
+     *
+     * @param x the first value
+     * @param y the second value
+     * @return the result
+     * @throws ArithmeticException if the result overflows an int
+     * @since 1.8
+     */
+    public static int multiplyExact(int x, int y) {
+        long r = (long)x * (long)y;
+        if ((int)r != r) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return (int)r;
+    }
 }
--- a/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java	Thu Mar 23 15:00:29 2017 -0700
@@ -137,7 +137,7 @@
         if (decrypting) {
             result = inputLen - 16;
         } else {
-            result = inputLen + 16;
+            result = CipherCore.addExact(inputLen, 16);
         }
         return (result < 0? 0:result);
     }
@@ -453,12 +453,15 @@
         }
 
         byte[] cks = getChecksum(keyVal);
-        byte[] out = new byte[iv.length + keyVal.length + cks.length];
+        byte[] out = new byte[CipherCore.addExact(iv.length,
+                CipherCore.addExact(keyVal.length, cks.length))];
 
         System.arraycopy(keyVal, 0, out, iv.length, keyVal.length);
-        System.arraycopy(cks, 0, out, iv.length+keyVal.length, cks.length);
-        cipher.encrypt(out, iv.length, keyVal.length+cks.length,
-                       out, iv.length);
+        System.arraycopy(cks, 0, out,
+                CipherCore.addExact(iv.length, keyVal.length), cks.length);
+
+        cipher.encrypt(out, iv.length,
+                CipherCore.addExact(keyVal.length, cks.length), out, iv.length);
 
         System.arraycopy(iv, 0, out, 0, iv.length);
         // reverse the array content
--- a/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java	Thu Mar 23 15:00:29 2017 -0700
@@ -63,15 +63,16 @@
         if (in == null)
             return;
 
-        if ((off + len) > in.length) {
+        int idx = CipherCore.addExact(off, len);
+        if (idx > in.length) {
             throw new ShortBufferException("Buffer too small to hold padding");
         }
 
         byte paddingOctet = (byte) (len & 0xff);
-        byte[] padding = new byte[len];
+        byte[] padding = new byte[len -1];
         SunJCE.RANDOM.nextBytes(padding);
-        padding[len-1] = paddingOctet;
-        System.arraycopy(padding, 0, in, off, len);
+        System.arraycopy(padding, 0, in, off, len - 1);
+        in[idx - 1] = paddingOctet;
         return;
     }
 
@@ -94,14 +95,15 @@
             return 0;
         }
 
-        byte lastByte = in[off + len - 1];
+        int idx = CipherCore.addExact(off, len);
+        byte lastByte = in[idx - 1];
         int padValue = (int)lastByte & 0x0ff;
         if ((padValue < 0x01)
             || (padValue > blockSize)) {
             return -1;
         }
 
-        int start = off + len - ((int)lastByte & 0x0ff);
+        int start = idx - padValue;
         if (start < off) {
             return -1;
         }
--- a/src/share/classes/com/sun/crypto/provider/PBECipherCore.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PBECipherCore.java	Thu Mar 23 15:00:29 2017 -0700
@@ -264,7 +264,7 @@
 
         if (algo.equals("DES")) {
             // P || S (password concatenated with salt)
-            byte[] concat = new byte[passwdBytes.length + salt.length];
+            byte[] concat = new byte[CipherCore.addExact(passwdBytes.length, salt.length)];
             System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
             java.util.Arrays.fill(passwdBytes, (byte)0x00);
             System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
--- a/src/share/classes/com/sun/crypto/provider/PKCS5Padding.java	Thu May 18 17:01:00 2017 +0100
+++ b/src/share/classes/com/sun/crypto/provider/PKCS5Padding.java	Thu Mar 23 15:00:29 2017 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -26,6 +26,7 @@
 package com.sun.crypto.provider;
 
 import javax.crypto.ShortBufferException;
+import java.util.Arrays;
 
 /**
  * This class implements padding as specified in the PKCS#5 standard.
@@ -63,14 +64,13 @@
         if (in == null)
             return;
 
-        if ((off + len) > in.length) {
+        int idx = CipherCore.addExact(off, len);
+        if (idx > in.length) {
             throw new ShortBufferException("Buffer too small to hold padding");
         }
 
         byte paddingOctet = (byte) (len & 0xff);
-        for (int i = 0; i < len; i++) {
-            in[i + off] = paddingOctet;
-        }
+        Arrays.fill(in, off, idx, paddingOctet);
         return;
     }
 
@@ -92,25 +92,24 @@
             (len == 0)) { // this can happen if input is really a padded buffer
             return 0;
         }
-
-        byte lastByte = in[off + len - 1];
+        int idx = CipherCore.addExact(off, len);
+        byte lastByte = in[idx - 1];
         int padValue = (int)lastByte & 0x0ff;
         if ((padValue < 0x01)
             || (padValue > blockSize)) {
             return -1;
         }
 
-        int start = off + len - ((int)lastByte & 0x0ff);
+        int start = idx - padValue;
         if (start < off) {
             return -1;
         }
 
-        for (int i = 0; i < ((int)lastByte & 0x0ff); i++) {
-            if (in[start+i] != lastByte) {
+        for (int i = start; i < idx; i++) {
+            if (in[i] != lastByte) {
                 return -1;
             }
         }
-
         return start;
     }