Mercurial > hg > release > icedtea7-forest-2.6 > jdk
changeset 9709:80dd958417a8
8209862: CipherCore performance improvement
Reviewed-by: apetcher, ascarpino
Contributed-by: sergey.kuksenko@oracle.com, sean.coffey@oracle.com
author | coffeys |
---|---|
date | Wed, 13 Feb 2019 05:22:12 +0000 |
parents | 3262853a2746 |
children | 83079b594f5e |
files | src/share/classes/com/sun/crypto/provider/CipherCore.java |
diffstat | 1 files changed, 113 insertions(+), 68 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/CipherCore.java Wed Feb 13 04:58:54 2019 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java Wed Feb 13 05:22:12 2019 +0000 @@ -215,11 +215,10 @@ 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 @@ -713,12 +712,19 @@ */ 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); + 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); @@ -775,20 +781,78 @@ BadPaddingException { 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 = addExact(buffered, inputLen); - // calculate padding length int totalLen = addExact(len, cipher.getBufferedLength()); int paddingLen = 0; @@ -818,18 +882,15 @@ * - 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[addExact(len, paddingLen)]; - finalOffset = 0; if (buffered != 0) { System.arraycopy(buffer, 0, finalBuf, 0, buffered); if (!decrypting) { @@ -840,69 +901,53 @@ } if (inputLen != 0) { System.arraycopy(input, inputOffset, finalBuf, - buffered, inputLen); + buffered, inputLen); } if (paddingLen != 0) { padding.padWithLen(finalBuf, 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); + return input; + } - 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; + 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); } - 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); - } else { // encrypting - try { - outLen = finalNoPadding(finalBuf, finalOffset, output, - outputOffset, finalBufLen); - } finally { + return len; + } finally { + if (!decrypting) { if (finalBuf != input) { // done with internal finalBuf array. Copied to output Arrays.fill(finalBuf, (byte) 0x00); } } } + } - 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 outLen; + return outputCapacity; } private int finalNoPadding(byte[] in, int inOfs, byte[] out, int outOfs,