From 04711e846fda07ab7f3284f53316ac1e7b141e5a Mon Sep 17 00:00:00 2001 From: Kostas Tsiounis Date: Wed, 21 Jun 2023 09:50:28 -0400 Subject: [PATCH] Improve speed of cipher operations for large inputs --- .../com/sun/crypto/provider/CipherCore.java | 59 +++++++++++++++---- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java b/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java index 2cddea6399d..dc76dfa3e65 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java @@ -749,12 +749,26 @@ byte[] doFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { try { byte[] output = new byte[getOutputSizeByOperation(inputLen, true)]; - byte[] finalBuf = prepareInputBuffer(input, inputOffset, - inputLen, output, 0); + int outputOffset = 0; + int outLen = 0; + + if (inputLen > 0) { + /* + * Call the update() method to get rid of as many bytes as + * possible before potentially copying array. + */ + int updateOutLen = update(input, inputOffset, inputLen, output, outputOffset); + inputOffset = inputLen; + inputLen = 0; + outputOffset += updateOutLen; + outLen = updateOutLen; + } + + byte[] finalBuf = prepareInputBuffer(input, inputOffset, inputLen, output, outputOffset); int finalOffset = (finalBuf == input) ? inputOffset : 0; int finalBufLen = (finalBuf == input) ? inputLen : finalBuf.length; - int outLen = fillOutputBuffer(finalBuf, finalOffset, output, 0, + outLen += fillOutputBuffer(finalBuf, finalOffset, output, outputOffset, finalBufLen, input); endDoFinal(); @@ -818,13 +832,6 @@ int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int estOutSize = getOutputSizeByOperation(inputLen, true); int outputCapacity = checkOutputCapacity(output, outputOffset, estOutSize); - int offset = outputOffset; - byte[] finalBuf = prepareInputBuffer(input, inputOffset, - inputLen, output, outputOffset); - byte[] internalOutput = 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 @@ -835,18 +842,44 @@ int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, if (outputCapacity < estOutSize) { cipher.save(); } + } + + int outLen = 0; + int estFinalBuffSize = estOutSize; + if (inputLen > 0) { + /* + * Call the update() method to get rid of as many bytes as + * possible before potentially copying array. + */ + int updateOutLen = update(input, inputOffset, inputLen, output, outputOffset); + inputOffset = inputLen; + inputLen = 0; + outputOffset += updateOutLen; + outLen += updateOutLen; + estFinalBuffSize -= updateOutLen; + } + + int offset = outputOffset; + byte[] finalBuf = prepareInputBuffer(input, inputOffset, inputLen, output, outputOffset); + byte[] internalOutput = null; // for decrypting only + + int finalOffset = (finalBuf == input) ? inputOffset : 0; + int finalBufLen = (finalBuf == input) ? inputLen : finalBuf.length; + + if (decrypting) { if (outputCapacity < estOutSize || padding != null) { // create temporary output buffer if the estimated size is larger // than the user-provided buffer or a padding needs to be removed // before copying the unpadded result to the output buffer - internalOutput = new byte[estOutSize]; + internalOutput = new byte[estFinalBuffSize]; offset = 0; } } byte[] outBuffer = (internalOutput != null) ? internalOutput : output; - int outLen = fillOutputBuffer(finalBuf, finalOffset, outBuffer, + int outBuffLen = fillOutputBuffer(finalBuf, finalOffset, outBuffer, offset, finalBufLen, input); + outLen += outBuffLen; if (decrypting) { @@ -860,7 +893,7 @@ int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, // copy the result into user-supplied output buffer if (internalOutput != null) { System.arraycopy(internalOutput, 0, output, outputOffset, - outLen); + outBuffLen); // decrypt mode. Zero out output data that's not required Arrays.fill(internalOutput, (byte) 0x00); }