diff --git a/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java b/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java index 8ad6401ce9c..6eadbd74306 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, 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 @@ -39,7 +39,6 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.util.Arrays; -import java.util.Objects; import jdk.internal.HotSpotIntrinsicCandidate; @@ -351,8 +350,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants */ void encryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) { - Objects.checkFromIndexSize(inOffset, AES_BLOCK_SIZE, in.length); - Objects.checkFromIndexSize(outOffset, AES_BLOCK_SIZE, out.length); + // Array bound checks are done in caller code, i.e. + // FeedbackCipher.encrypt/decrypt(...) to improve performance. implEncryptBlock(in, inOffset, out, outOffset); } @@ -430,8 +429,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants */ void decryptBlock(byte[] in, int inOffset, byte[] out, int outOffset) { - Objects.checkFromIndexSize(inOffset, AES_BLOCK_SIZE, in.length); - Objects.checkFromIndexSize(outOffset, AES_BLOCK_SIZE, out.length); + // Array bound checks are done in caller code, i.e. + // FeedbackCipher.encrypt/decrypt(...) to improve performance. implDecryptBlock(in, inOffset, out, outOffset); } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java b/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java index 4e93d6fe03a..91a6e647da7 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/CipherBlockChaining.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -30,6 +30,7 @@ import java.security.ProviderException; import java.util.Objects; import jdk.internal.HotSpotIntrinsicCandidate; +import sun.security.util.ArrayUtil; /** @@ -145,9 +146,9 @@ class CipherBlockChaining extends FeedbackCipher { if (plainLen <= 0) { return plainLen; } - cryptBlockSizeCheck(plainLen); - cryptNullAndBoundsCheck(plain, plainOffset, plainLen); - cryptNullAndBoundsCheck(cipher, cipherOffset, plainLen); + ArrayUtil.blockSizeCheck(plainLen, blockSize); + ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen); + ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen); return implEncrypt(plain, plainOffset, plainLen, cipher, cipherOffset); } @@ -196,9 +197,9 @@ class CipherBlockChaining extends FeedbackCipher { if (cipherLen <= 0) { return cipherLen; } - cryptBlockSizeCheck(cipherLen); - cryptNullAndBoundsCheck(cipher, cipherOffset, cipherLen); - cryptNullAndBoundsCheck(plain, plainOffset, cipherLen); + ArrayUtil.blockSizeCheck(cipherLen, blockSize); + ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen); + ArrayUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen); return implDecrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); } @@ -218,23 +219,4 @@ class CipherBlockChaining extends FeedbackCipher { } return cipherLen; } - - private void cryptBlockSizeCheck(int len) { - if ((len % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } - } - - private static void cryptNullAndBoundsCheck(byte[] array, int offset, int len) { - Objects.requireNonNull(array); - - if (offset < 0 || offset >= array.length) { - throw new ArrayIndexOutOfBoundsException(offset); - } - - int endIndex = offset + len - 1; - if (endIndex < 0 || endIndex >= array.length) { - throw new ArrayIndexOutOfBoundsException(endIndex); - } - } } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/CipherFeedback.java b/src/java.base/share/classes/com/sun/crypto/provider/CipherFeedback.java index 84b527efe5b..71e94cc7ffa 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/CipherFeedback.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/CipherFeedback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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,6 +27,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; import java.security.ProviderException; +import sun.security.util.ArrayUtil; /** * This class represents ciphers in cipher-feedback (CFB) mode. @@ -149,9 +150,9 @@ final class CipherFeedback extends FeedbackCipher { */ int encrypt(byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset) { - if ((plainLen % numBytes) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + ArrayUtil.blockSizeCheck(plainLen, numBytes); + ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen); + ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen); int nShift = blockSize - numBytes; int loopCount = plainLen / numBytes; @@ -225,9 +226,10 @@ final class CipherFeedback extends FeedbackCipher { */ int decrypt(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset) { - if ((cipherLen % numBytes) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + + ArrayUtil.blockSizeCheck(cipherLen, numBytes); + ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen); + ArrayUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen); int nShift = blockSize - numBytes; int loopCount = cipherLen / numBytes; diff --git a/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java index 4503ec0e170..49d2139bd59 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/CounterMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, 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,9 +26,9 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; -import java.util.Objects; import jdk.internal.HotSpotIntrinsicCandidate; +import sun.security.util.ArrayUtil; /** * This class represents ciphers in counter (CTR) mode. @@ -175,8 +175,9 @@ class CounterMode extends FeedbackCipher { if (len == 0) { return 0; } - Objects.checkFromIndexSize(inOff, len, in.length); - Objects.checkFromIndexSize(outOff, len, out.length); + + ArrayUtil.nullAndBoundsCheck(in, inOff, len); + ArrayUtil.nullAndBoundsCheck(out, outOff, len); return implCrypt(in, inOff, len, out, outOff); } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java b/src/java.base/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java index 334e4245e27..24e85adb9ba 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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,6 +27,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; import java.security.ProviderException; +import sun.security.util.ArrayUtil; /** * This class represents ciphers in electronic codebook (ECB) mode. @@ -112,9 +113,10 @@ final class ElectronicCodeBook extends FeedbackCipher { * @return the length of the encrypted data */ int encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { - if ((len % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + ArrayUtil.blockSizeCheck(len, blockSize); + ArrayUtil.nullAndBoundsCheck(in, inOff, len); + ArrayUtil.nullAndBoundsCheck(out, outOff, len); + for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.encryptBlock(in, inOff, out, outOff); inOff += blockSize; @@ -141,9 +143,10 @@ final class ElectronicCodeBook extends FeedbackCipher { * @return the length of the decrypted data */ int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { - if ((len % blockSize) != 0) { - throw new ProviderException("Internal error in input buffering"); - } + ArrayUtil.blockSizeCheck(len, blockSize); + ArrayUtil.nullAndBoundsCheck(in, inOff, len); + ArrayUtil.nullAndBoundsCheck(out, outOff, len); + for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.decryptBlock(in, inOff, out, outOff); inOff += blockSize; diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index 6ea2b3a66eb..16d4fd4886f 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -30,6 +30,8 @@ import java.io.*; import java.security.*; import javax.crypto.*; import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; +import sun.security.util.ArrayUtil; + /** * This class represents ciphers in GaloisCounter (GCM) mode. @@ -406,8 +408,8 @@ final class GaloisCounterMode extends FeedbackCipher { /** * Performs encryption operation. * - *
The input plain text in
, starting at inOff
- * and ending at (inOff + len - 1)
, is encrypted. The result
+ *
The input plain text in
, starting at inOfs
+ * and ending at (inOfs + len - 1)
, is encrypted. The result
* is stored in out
, starting at outOfs
.
*
* @param in the buffer with the input data to be encrypted
@@ -420,18 +422,21 @@ final class GaloisCounterMode extends FeedbackCipher {
* @return the number of bytes placed into the out
buffer
*/
int encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
- if ((len % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ ArrayUtil.blockSizeCheck(len, blockSize);
checkDataLength(processed, len);
processAAD();
+
if (len > 0) {
+ ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
+ ArrayUtil.nullAndBoundsCheck(out, outOfs, len);
+
gctrPAndC.update(in, inOfs, len, out, outOfs);
processed += len;
ghashAllToS.update(out, outOfs, len);
}
+
return len;
}
@@ -451,7 +456,10 @@ final class GaloisCounterMode extends FeedbackCipher {
throw new ShortBufferException
("Can't fit both data and tag into one buffer");
}
- if (out.length - outOfs < (len + tagLenBytes)) {
+ try {
+ ArrayUtil.nullAndBoundsCheck(out, outOfs,
+ (len + tagLenBytes));
+ } catch (ArrayIndexOutOfBoundsException aiobe) {
throw new ShortBufferException("Output buffer too small");
}
@@ -459,6 +467,8 @@ final class GaloisCounterMode extends FeedbackCipher {
processAAD();
if (len > 0) {
+ ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
+
doLastBlock(in, inOfs, len, out, outOfs, true);
}
@@ -492,9 +502,7 @@ final class GaloisCounterMode extends FeedbackCipher {
* @return the number of bytes placed into the out
buffer
*/
int decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
- if ((len % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ ArrayUtil.blockSizeCheck(len, blockSize);
checkDataLength(ibuffer.size(), len);
@@ -504,6 +512,7 @@ final class GaloisCounterMode extends FeedbackCipher {
// store internally until decryptFinal is called because
// spec mentioned that only return recovered data after tag
// is successfully verified
+ ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
ibuffer.write(in, inOfs, len);
}
return 0;
@@ -532,22 +541,28 @@ final class GaloisCounterMode extends FeedbackCipher {
if (len < tagLenBytes) {
throw new AEADBadTagException("Input too short - need tag");
}
+
// do this check here can also catch the potential integer overflow
// scenario for the subsequent output buffer capacity check.
checkDataLength(ibuffer.size(), (len - tagLenBytes));
- if (out.length - outOfs < ((ibuffer.size() + len) - tagLenBytes)) {
+ try {
+ ArrayUtil.nullAndBoundsCheck(out, outOfs,
+ (ibuffer.size() + len) - tagLenBytes);
+ } catch (ArrayIndexOutOfBoundsException aiobe) {
throw new ShortBufferException("Output buffer too small");
}
processAAD();
+ ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
+
// get the trailing tag bytes from 'in'
byte[] tag = new byte[tagLenBytes];
System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes);
len -= tagLenBytes;
- if (len != 0) {
+ if (len > 0) {
ibuffer.write(in, inOfs, len);
}
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java b/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java
index 47d9d63c93d..7b518836cd1 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
import java.security.ProviderException;
+import sun.security.util.ArrayUtil;
/**
* This class represents ciphers in output-feedback (OFB) mode.
@@ -148,10 +149,10 @@ final class OutputFeedback extends FeedbackCipher {
*/
int encrypt(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset) {
+ ArrayUtil.blockSizeCheck(plainLen, numBytes);
+ ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
- if ((plainLen % numBytes) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
int nShift = blockSize - numBytes;
int loopCount = plainLen / numBytes;
@@ -189,6 +190,9 @@ final class OutputFeedback extends FeedbackCipher {
*/
int encryptFinal(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset) {
+ ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
+
int oddBytes = plainLen % numBytes;
int len = encrypt(plain, plainOffset, (plainLen - oddBytes),
cipher, cipherOffset);
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PCBC.java b/src/java.base/share/classes/com/sun/crypto/provider/PCBC.java
index fd99bb0cbd5..544776ec04f 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/PCBC.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PCBC.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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,6 +27,7 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
import java.security.ProviderException;
+import sun.security.util.ArrayUtil;
/**
@@ -136,9 +137,10 @@ final class PCBC extends FeedbackCipher {
int encrypt(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset)
{
- if ((plainLen % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ ArrayUtil.blockSizeCheck(plainLen, blockSize);
+ ArrayUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
+
int i;
int endIndex = plainOffset + plainLen;
@@ -176,9 +178,10 @@ final class PCBC extends FeedbackCipher {
int decrypt(byte[] cipher, int cipherOffset, int cipherLen,
byte[] plain, int plainOffset)
{
- if ((cipherLen % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ ArrayUtil.blockSizeCheck(cipherLen, blockSize);
+ ArrayUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen);
+ ArrayUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen);
+
int i;
int endIndex = cipherOffset + cipherLen;
diff --git a/src/java.base/share/classes/sun/security/util/ArrayUtil.java b/src/java.base/share/classes/sun/security/util/ArrayUtil.java
new file mode 100644
index 00000000000..759bc950b6d
--- /dev/null
+++ b/src/java.base/share/classes/sun/security/util/ArrayUtil.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.util.List;
+import java.util.function.BiFunction;
+import java.security.*;
+import jdk.internal.util.Preconditions;
+
+
+/**
+ * This class holds the various utility methods for array range checks.
+ */
+
+public final class ArrayUtil {
+
+ private static final BiFunction