Skip to content

Commit

Permalink
Improve speed of cipher operations for large inputs and allow unpaddi…
Browse files Browse the repository at this point in the history
…ng at offset of output
  • Loading branch information
KostasTsiounis committed Jun 27, 2023
1 parent 89b7f69 commit 921a3e4
Showing 1 changed file with 50 additions and 19 deletions.
69 changes: 50 additions & 19 deletions src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -897,12 +897,26 @@ byte[] doFinal(byte[] input, int inputOffset, int inputLen)
try {
checkReinit();
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();
Expand Down Expand Up @@ -967,13 +981,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; // 0 for decrypting
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
Expand All @@ -984,18 +991,43 @@ 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) {

Expand All @@ -1009,7 +1041,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);
System.arraycopy(internalOutput, 0, output, outputOffset, outBuffLen);
// decrypt mode. Zero out output data that's not required
Arrays.fill(internalOutput, (byte) 0x00);
}
Expand All @@ -1026,16 +1058,15 @@ private void endDoFinal() {
}
}

private int unpad(int outLen, byte[] outWithPadding)
private int unpad(int outLen, int off, byte[] outWithPadding)
throws BadPaddingException {
int padStart = padding.unpad(outWithPadding, 0, outLen);
int padStart = padding.unpad(outWithPadding, off, 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;
return padStart - off;
}

private byte[] prepareInputBuffer(byte[] input, int inputOffset,
Expand Down Expand Up @@ -1111,7 +1142,7 @@ private int fillOutputBuffer(byte[] finalBuf, int finalOffset,
len = finalNoPadding(finalBuf, finalOffset, output,
outOfs, finalBufLen);
if (decrypting && padding != null) {
len = unpad(len, output);
len = unpad(len, outOfs, output);
}
return len;
} finally {
Expand Down

0 comments on commit 921a3e4

Please sign in to comment.