提交 976021bc 编写于 作者: C coffeys

8209862: CipherCore performance improvement

Reviewed-by: apetcher, ascarpino
Contributed-by: sergey.kuksenko@oracle.com, sean.coffey@oracle.com
上级 007c88f9
......@@ -253,11 +253,10 @@ final class CipherCore {
return result;
}
/**
* Sets the padding mechanism of this cipher.
*
* @param padding the padding mechanism
* @param paddingScheme the padding mechanism
*
* @exception NoSuchPaddingException if the requested padding mechanism
* does not exist
......@@ -660,10 +659,7 @@ final class CipherCore {
* (e.g., has not been initialized)
*/
byte[] update(byte[] input, int inputOffset, int inputLen) {
if (requireReinit) {
throw new IllegalStateException
("Must use either different key or iv for GCM encryption");
}
checkReinit();
byte[] output = null;
try {
......@@ -711,10 +707,7 @@ final class CipherCore {
*/
int update(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException {
if (requireReinit) {
throw new IllegalStateException
("Must use either different key or iv for GCM encryption");
}
checkReinit();
// figure out how much can be sent to crypto function
int len = Math.addExact(buffered, inputLen);
......@@ -849,12 +842,20 @@ final class CipherCore {
*/
byte[] doFinal(byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException, BadPaddingException {
byte[] output = null;
try {
output = new byte[getOutputSizeByOperation(inputLen, true)];
int len = doFinal(input, inputOffset, inputLen, output, 0);
if (len < output.length) {
byte[] copy = Arrays.copyOf(output, len);
checkReinit();
byte[] output = new byte[getOutputSizeByOperation(inputLen, true)];
byte[] finalBuf = prepareInputBuffer(input, inputOffset,
inputLen, output, 0);
int finalOffset = (finalBuf == input) ? inputOffset : 0;
int finalBufLen = (finalBuf == input) ? inputLen : finalBuf.length;
int outLen = fillOutputBuffer(finalBuf, finalOffset, output, 0,
finalBufLen, input);
endDoFinal();
if (outLen < output.length) {
byte[] copy = Arrays.copyOf(output, outLen);
if (decrypting) {
// Zero out internal (ouput) array
Arrays.fill(output, (byte) 0x00);
......@@ -909,26 +910,81 @@ final class CipherCore {
int outputOffset)
throws IllegalBlockSizeException, ShortBufferException,
BadPaddingException {
if (requireReinit) {
throw new IllegalStateException
("Must use either different key or iv for GCM encryption");
}
checkReinit();
int estOutSize = getOutputSizeByOperation(inputLen, true);
// check output buffer capacity.
// if we are decrypting with padding applied, we can perform this
// check only after we have determined how many padding bytes there
// are.
int outputCapacity = output.length - outputOffset;
int minOutSize = (decrypting? (estOutSize - blockSize):estOutSize);
if ((output == null) || (outputCapacity < minOutSize)) {
throw new ShortBufferException("Output buffer must be "
+ "(at least) " + minOutSize + " bytes long");
int outputCapacity = checkOutputCapacity(output, outputOffset,
estOutSize);
int offset = decrypting ? 0 : outputOffset; // 0 for decrypting
byte[] finalBuf = prepareInputBuffer(input, inputOffset,
inputLen, output, outputOffset);
byte[] outWithPadding = null; // for decrypting only
int finalOffset = (finalBuf == input) ? inputOffset : 0;
int finalBufLen = (finalBuf == input) ? inputLen : finalBuf.length;
if (decrypting) {
// if the size of specified output buffer is less than
// the length of the cipher text, then the current
// content of cipher has to be preserved in order for
// users to retry the call with a larger buffer in the
// case of ShortBufferException.
if (outputCapacity < estOutSize) {
cipher.save();
}
// create temporary output buffer so that only "real"
// data bytes are passed to user's output buffer.
outWithPadding = new byte[estOutSize];
}
byte[] outBuffer = decrypting ? outWithPadding : output;
int outLen = fillOutputBuffer(finalBuf, finalOffset, outBuffer,
offset, finalBufLen, input);
if (decrypting) {
if (outputCapacity < outLen) {
// restore so users can retry with a larger buffer
cipher.restore();
throw new ShortBufferException("Output buffer too short: "
+ (outputCapacity)
+ " bytes given, " + outLen
+ " bytes needed");
}
// copy the result into user-supplied output buffer
System.arraycopy(outWithPadding, 0, output, outputOffset, outLen);
// decrypt mode. Zero out output data that's not required
Arrays.fill(outWithPadding, (byte) 0x00);
}
endDoFinal();
return outLen;
}
private void endDoFinal() {
buffered = 0;
diffBlocksize = blockSize;
if (cipherMode != ECB_MODE) {
cipher.reset();
}
}
private int unpad(int outLen, byte[] outWithPadding)
throws BadPaddingException {
int padStart = padding.unpad(outWithPadding, 0, outLen);
if (padStart < 0) {
throw new BadPaddingException("Given final block not " +
"properly padded. Such issues can arise if a bad key " +
"is used during decryption.");
}
outLen = padStart;
return outLen;
}
private byte[] prepareInputBuffer(byte[] input, int inputOffset,
int inputLen, byte[] output, int outputOffset)
throws IllegalBlockSizeException, ShortBufferException {
// calculate total input length
int len = Math.addExact(buffered, inputLen);
// calculate padding length
int totalLen = Math.addExact(len, cipher.getBufferedLength());
int paddingLen = 0;
......@@ -958,18 +1014,15 @@ final class CipherCore {
* - there are internally buffered bytes
* - doing encryption and padding is needed
*/
byte[] finalBuf = input;
int finalOffset = inputOffset;
int finalBufLen = inputLen;
if ((buffered != 0) || (!decrypting && padding != null) ||
((input == output)
&& (outputOffset - inputOffset < inputLen)
&& (inputOffset - outputOffset < buffer.length))) {
byte[] finalBuf;
if (decrypting || padding == null) {
paddingLen = 0;
}
finalBuf = new byte[Math.addExact(len, paddingLen)];
finalOffset = 0;
if (buffered != 0) {
System.arraycopy(buffer, 0, finalBuf, 0, buffered);
if (!decrypting) {
......@@ -980,56 +1033,31 @@ final class CipherCore {
}
if (inputLen != 0) {
System.arraycopy(input, inputOffset, finalBuf,
buffered, inputLen);
buffered, inputLen);
}
if (paddingLen != 0) {
padding.padWithLen(finalBuf, Math.addExact(buffered, inputLen), paddingLen);
}
finalBufLen = finalBuf.length;
return finalBuf;
}
int outLen = 0;
if (decrypting) {
// if the size of specified output buffer is less than
// the length of the cipher text, then the current
// content of cipher has to be preserved in order for
// users to retry the call with a larger buffer in the
// case of ShortBufferException.
if (outputCapacity < estOutSize) {
cipher.save();
}
// create temporary output buffer so that only "real"
// data bytes are passed to user's output buffer.
byte[] outWithPadding = new byte[estOutSize];
outLen = finalNoPadding(finalBuf, finalOffset, outWithPadding,
0, finalBufLen);
if (padding != null) {
int padStart = padding.unpad(outWithPadding, 0, outLen);
if (padStart < 0) {
throw new BadPaddingException("Given final block not " +
"properly padded. Such issues can arise if a bad key " +
"is used during decryption.");
}
outLen = padStart;
}
return input;
}
if (outputCapacity < outLen) {
// restore so users can retry with a larger buffer
cipher.restore();
throw new ShortBufferException("Output buffer too short: "
+ (outputCapacity)
+ " bytes given, " + outLen
+ " bytes needed");
private int fillOutputBuffer(byte[] finalBuf, int finalOffset,
byte[] output, int outOfs, int finalBufLen,
byte[] input)
throws ShortBufferException, BadPaddingException,
IllegalBlockSizeException {
int len;
try {
len = finalNoPadding(finalBuf, finalOffset, output,
outOfs, finalBufLen);
if (decrypting && padding != null) {
len = unpad(len, output);
}
// copy the result into user-supplied output buffer
System.arraycopy(outWithPadding, 0, output, outputOffset, outLen);
// decrypt mode. Zero out output data that's not required
Arrays.fill(outWithPadding, (byte) 0x00);
} else { // encrypting
try {
outLen = finalNoPadding(finalBuf, finalOffset, output,
outputOffset, finalBufLen);
} finally {
return len;
} finally {
if (!decrypting) {
// reset after doFinal() for GCM encryption
requireReinit = (cipherMode == GCM_MODE);
if (finalBuf != input) {
......@@ -1038,13 +1066,28 @@ final class CipherCore {
}
}
}
}
buffered = 0;
diffBlocksize = blockSize;
if (cipherMode != ECB_MODE) {
cipher.reset();
private int checkOutputCapacity(byte[] output, int outputOffset,
int estOutSize) throws ShortBufferException {
// check output buffer capacity.
// if we are decrypting with padding applied, we can perform this
// check only after we have determined how many padding bytes there
// are.
int outputCapacity = output.length - outputOffset;
int minOutSize = decrypting ? (estOutSize - blockSize) : estOutSize;
if ((output == null) || (outputCapacity < minOutSize)) {
throw new ShortBufferException("Output buffer must be "
+ "(at least) " + minOutSize + " bytes long");
}
return outputCapacity;
}
private void checkReinit() {
if (requireReinit) {
throw new IllegalStateException
("Must use either different key or iv for GCM encryption");
}
return outLen;
}
private int finalNoPadding(byte[] in, int inOfs, byte[] out, int outOfs,
......@@ -1177,10 +1220,7 @@ final class CipherCore {
* @since 1.8
*/
void updateAAD(byte[] src, int offset, int len) {
if (requireReinit) {
throw new IllegalStateException
("Must use either different key or iv for GCM encryption");
}
checkReinit();
cipher.updateAAD(src, offset, len);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册