Mercurial > hg > openjdk > bsd-port > jdk
changeset 8764:219100e82eb2
8171252: Improve exception checking
8158517: Minor optimizations to ISO10126PADDING
Reviewed-by: ascarpino, mschoene
author | igerasim |
---|---|
date | Fri, 10 Nov 2017 19:04:43 +0000 |
parents | 227722ebc440 |
children | 913bf28ef6e7 |
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, 141 insertions(+), 54 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/AESCipher.java Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/AESCipher.java Fri Nov 10 19:04:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -140,7 +140,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 +479,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 Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/AESWrapCipher.java Fri Nov 10 19:04:43 2017 +0000 @@ -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 @@ -156,7 +156,7 @@ if (decrypting) { result = inputLen - 8; } else { - result = inputLen + 8; + result = CipherCore.addExact(inputLen, 8); } return (result < 0? 0:result); } @@ -378,7 +378,7 @@ throw new InvalidKeyException("Invalid key length: " + encoded.length + " bytes"); } - return encoded.length * 8; + return CipherCore.multiplyExact(encoded.length, 8); } /** @@ -404,7 +404,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 Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/ARCFOURCipher.java Fri Nov 10 19:04:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, 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 @@ -257,7 +257,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 Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/BlowfishCipher.java Fri Nov 10 19:04:43 2017 +0000 @@ -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 @@ -373,7 +373,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 Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java Fri Nov 10 19:04:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -270,7 +270,8 @@ } private int getOutputSizeByOperation(int inputLen, boolean isDoFinal) { - int totalLen = buffered + inputLen + cipher.getBufferedLength(); + int totalLen = addExact(buffered, cipher.getBufferedLength()); + totalLen = addExact(totalLen, inputLen); switch (cipherMode) { default: if (padding != null && !decrypting) { @@ -279,10 +280,10 @@ totalLen = diffBlocksize; } else { int residue = (totalLen - diffBlocksize) % blockSize; - totalLen += (blockSize - residue); + totalLen = addExact(totalLen, (blockSize - residue)); } } else { - totalLen += padding.padLength(totalLen); + totalLen = addExact(totalLen, padding.padLength(totalLen)); } } break; @@ -578,7 +579,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; @@ -597,12 +599,12 @@ int outLen = 0; if (len != 0) { // there is some work to do if ((input == output) - && (outputOffset < (inputOffset + inputLen)) - && (inputOffset < (outputOffset + buffer.length))) { + && (outputOffset - inputOffset < inputLen) + && (inputOffset - outputOffset < buffer.length)) { // copy 'input' out to avoid its content being // overwritten prematurely. input = Arrays.copyOfRange(input, inputOffset, - inputOffset + inputLen); + addExact(inputOffset, inputLen)); inputOffset = 0; } if (len <= buffered) { @@ -624,13 +626,13 @@ if (bufferCapacity != 0) { temp = Math.min(bufferCapacity, inputConsumed); if (unitBytes != blockSize) { - temp -= ((buffered + temp) % unitBytes); + temp -= (addExact(buffered, temp) % unitBytes); } System.arraycopy(input, inputOffset, buffer, buffered, temp); - inputOffset += temp; + inputOffset = addExact(inputOffset, temp); inputConsumed -= temp; inputLen -= temp; - buffered += temp; + buffered = addExact(buffered, temp); } // process 'buffer' if (decrypting) { @@ -638,7 +640,7 @@ } else { outLen = cipher.encrypt(buffer, 0, buffered, output, outputOffset); } - outputOffset += outLen; + outputOffset = addExact(outputOffset, outLen); buffered = 0; } if (inputConsumed > 0) { // still has input to process @@ -670,7 +672,7 @@ if (inputLen > 0) { System.arraycopy(input, inputOffset, buffer, buffered, inputLen); - buffered += inputLen; + buffered = addExact(buffered, inputLen); } return outLen; } @@ -776,10 +778,10 @@ } // calculate total input length - int len = buffered + inputLen; + int len = addExact(buffered, inputLen); // calculate padding length - int totalLen = len + cipher.getBufferedLength(); + int totalLen = addExact(len, cipher.getBufferedLength()); int paddingLen = 0; // will the total input length be a multiple of blockSize? if (unitBytes != blockSize) { @@ -812,12 +814,12 @@ int finalBufLen = inputLen; if ((buffered != 0) || (!decrypting && padding != null) || ((input == output) - && (outputOffset < (inputOffset + inputLen)) - && (inputOffset < (outputOffset + buffer.length)))) { + && (outputOffset - inputOffset < inputLen) + && (inputOffset - outputOffset < buffer.length))) { if (decrypting || padding == null) { paddingLen = 0; } - finalBuf = new byte[len + paddingLen]; + finalBuf = new byte[addExact(len, paddingLen)]; finalOffset = 0; if (buffered != 0) { System.arraycopy(buffer, 0, finalBuf, 0, buffered); @@ -827,7 +829,7 @@ buffered, inputLen); } if (paddingLen != 0) { - padding.padWithLen(finalBuf, (buffered+inputLen), paddingLen); + padding.padWithLen(finalBuf, addExact(buffered, inputLen), paddingLen); } finalBufLen = finalBuf.length; } @@ -981,4 +983,88 @@ 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 + */ + 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 sum of its arguments, + * throwing an exception if the result overflows a {@code long}. + * + * @param x the first value + * @param y the second value + * @return the result + * @throws ArithmeticException if the result overflows a long + * @since 1.8 + */ + static long addExact(long x, long y) { + long 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("long 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 + */ + 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; + } + + /** + * Returns the product of the arguments, + * throwing an exception if the result overflows a {@code long}. + * + * @param x the first value + * @param y the second value + * @return the result + * @throws ArithmeticException if the result overflows a long + * @since 1.8 + */ + static long multiplyExact(long x, long y) { + long r = x * y; + long ax = Math.abs(x); + long ay = Math.abs(y); + if (((ax | ay) >>> 31 != 0)) { + // Some bits greater than 2^31 that might cause overflow + // Check the result using the divide operator + // and check for the special case of Long.MIN_VALUE * -1 + if (((y != 0) && (r / y != x)) || + (x == Long.MIN_VALUE && y == -1)) { + throw new ArithmeticException("long overflow"); + } + } + return r; + } }
--- a/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/DESedeWrapCipher.java Fri Nov 10 19:04:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2011, 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 @@ -140,7 +140,7 @@ if (decrypting) { result = inputLen - 16; // CHECKSUM_LEN + IV_LEN; } else { - result = inputLen + 16; + result = CipherCore.addExact(inputLen, 16); } return (result < 0? 0:result); } @@ -456,11 +456,11 @@ } byte[] cks = getChecksum(keyVal); - byte[] in = new byte[keyVal.length + CHECKSUM_LEN]; + byte[] in = new byte[CipherCore.addExact(keyVal.length, CHECKSUM_LEN)]; System.arraycopy(keyVal, 0, in, 0, keyVal.length); System.arraycopy(cks, 0, in, keyVal.length, CHECKSUM_LEN); - byte[] out = new byte[iv.length + in.length]; + byte[] out = new byte[CipherCore.addExact(iv.length, in.length)]; System.arraycopy(iv, 0, out, 0, iv.length); cipher.encrypt(in, 0, in.length, out, iv.length);
--- a/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/ISO10126Padding.java Fri Nov 10 19:04:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, 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 @@ -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 Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PBECipherCore.java Fri Nov 10 19:04:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -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 Fri Nov 10 17:31:46 2017 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PKCS5Padding.java Fri Nov 10 19:04:43 2017 +0000 @@ -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; }