8318756: Create better internal buffer for AEADs

Reviewed-by: djelinski
This commit is contained in:
Anthony Scarpino 2023-12-06 18:09:10 +00:00
parent a9cb120d03
commit dc9c77bebe
14 changed files with 1178 additions and 450 deletions

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.crypto.provider;
import jdk.internal.util.ArraysSupport;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HexFormat;
/**
* This class extends ByteArrayOutputStream by optimizing internal buffering.
* It skips bounds checking, as the buffers are known and input previously
* checked. toByteArray() returns the internal buffer to avoid an extra copy.
*
* This uses `count` to determine the state of `buf`. `buf` can still
* point to an array while `count` equals zero.
*/
final class AEADBufferedStream extends ByteArrayOutputStream {
/**
* Create an instance with the specified buffer
*/
public AEADBufferedStream(int len) {
super(len);
}
/**
* This method saves memory by returning the internal buffer. The calling
* method must use {@code size()} for the relevant data length as the
* returning byte[] maybe larger.
*
* @return internal buffer.
*/
public byte[] getBuffer() {
return buf;
}
/**
* This method with expand the buffer if {@code count} + {@code len}
* is larger than the buffer byte[] length.
* @param len length to add to the current buffer
*/
private void checkCapacity(int len) {
int blen = buf.length;
// Create a new larger buffer and append the new data
if (blen < count + len) {
buf = Arrays.copyOf(buf, ArraysSupport.newLength(blen, len, blen));
}
}
/**
* Takes a ByteBuffer writing non-blocksize data directly to the internal
* buffer.
* @param src remaining non-blocksize ByteBuffer
*/
public void write(ByteBuffer src) {
int pos = src.position();
int len = src.remaining();
if (src.hasArray()) {
write(src.array(), pos + src.arrayOffset(), len);
src.position(pos + len);
return;
}
checkCapacity(len);
src.get(buf, count, len);
count += len;
}
@Override
public void write(byte[] in, int offset, int len) {
checkCapacity(len);
System.arraycopy(in, offset, buf, count, len);
count += len;
}
@Override
public String toString() {
return (count == 0 ? "null" : HexFormat.of().formatHex(buf));
}
}

View file

@ -25,7 +25,6 @@
package com.sun.crypto.provider;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
@ -64,7 +63,6 @@ abstract class ChaCha20Cipher extends CipherSpi {
private static final int KS_MAX_LEN = 1024;
private static final int KS_BLK_SIZE = 64;
private static final int KS_SIZE_INTS = KS_BLK_SIZE / Integer.BYTES;
private static final int CIPHERBUF_BASE = 1024;
// The initialization state of the cipher
private boolean initialized;
@ -650,7 +648,7 @@ abstract class ChaCha20Cipher extends CipherSpi {
try {
engine.doUpdate(in, inOfs, inLen, out, 0);
} catch (ShortBufferException | KeyException exc) {
throw new RuntimeException(exc);
throw new ProviderException(exc);
}
return out;
@ -681,11 +679,35 @@ abstract class ChaCha20Cipher extends CipherSpi {
try {
bytesUpdated = engine.doUpdate(in, inOfs, inLen, out, outOfs);
} catch (KeyException ke) {
throw new RuntimeException(ke);
throw new ProviderException(ke);
}
return bytesUpdated;
}
/**
* Update the currently running operation with additional data
*
* @param input the plaintext or ciphertext ByteBuffer
* @param output ByteBuffer that will hold the resulting data. This
* must be large enough to hold the resulting data.
*
* @return the length in bytes of the data written into the {@code out}
* buffer.
*
* @throws ShortBufferException if the buffer {@code out} does not have
* enough space to hold the resulting data.
*/
@Override
protected int engineUpdate(ByteBuffer input, ByteBuffer output)
throws ShortBufferException {
try {
return bufferCrypt(input, output, true);
} catch (AEADBadTagException e) {
// exception is never thrown by update ops
throw new AssertionError(e);
}
}
/**
* Complete the currently running operation using any final
* data provided by the caller.
@ -753,6 +775,118 @@ abstract class ChaCha20Cipher extends CipherSpi {
return bytesUpdated;
}
/**
* Complete the currently running operation using any final
* data provided by the caller.
*
* @param input the plaintext or ciphertext input bytebuffer.
* @param output ByteBuffer that will hold the resulting data. This
* must be large enough to hold the resulting data.
*
* @return the resulting plaintext or ciphertext bytes.
*
* @throws AEADBadTagException if, during decryption, the provided tag
* does not match the calculated tag.
*/
@Override
protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
throws ShortBufferException, AEADBadTagException {
return bufferCrypt(input, output, false);
}
/*
* Optimized version of bufferCrypt from CipherSpi.java. Direct
* ByteBuffers send to the engine code.
*/
private int bufferCrypt(ByteBuffer input, ByteBuffer output,
boolean isUpdate) throws ShortBufferException, AEADBadTagException {
if ((input == null) || (output == null)) {
throw new NullPointerException
("Input and output buffers must not be null");
}
int inPos = input.position();
int inLimit = input.limit();
int inLen = inLimit - inPos;
if (isUpdate && (inLen == 0)) {
return 0;
}
int outLenNeeded = engine.getOutputSize(inLen, !isUpdate);
if (output.remaining() < outLenNeeded) {
throw new ShortBufferException("Need at least " + outLenNeeded
+ " bytes of space in output buffer");
}
int total = 0;
// Check if input bytebuffer is heap-backed
if (input.hasArray()) {
byte[] inArray = input.array();
int inOfs = input.arrayOffset() + inPos;
byte[] outArray;
// Check if output bytebuffer is heap-backed
if (output.hasArray()) {
outArray = output.array();
int outPos = output.position();
int outOfs = output.arrayOffset() + outPos;
// check array address and offsets and use temp output buffer
// if output offset is larger than input offset and
// falls within the range of input data
boolean useTempOut = false;
if (inArray == outArray &&
((inOfs < outOfs) && (outOfs < inOfs + inLen))) {
useTempOut = true;
outArray = new byte[outLenNeeded];
outOfs = 0;
}
try {
if (isUpdate) {
total = engine.doUpdate(inArray, inOfs, inLen, outArray,
outOfs);
} else {
total = engine.doFinal(inArray, inOfs, inLen, outArray,
outOfs);
}
} catch (KeyException e) {
throw new ProviderException(e);
}
if (useTempOut) {
output.put(outArray, outOfs, total);
} else {
// adjust output position manually
output.position(outPos + total);
}
} else { // if output is direct
if (isUpdate) {
outArray = engineUpdate(inArray, inOfs, inLen);
} else {
outArray = engineDoFinal(inArray, inOfs, inLen);
}
if (outArray != null && outArray.length != 0) {
output.put(outArray);
total = outArray.length;
}
}
// adjust input position manually
input.position(inLimit);
} else { // Bytebuffers are both direct
try {
if (isUpdate) {
return engine.doUpdate(input, output);
}
return engine.doFinal(input, output);
} catch (KeyException e) {
throw new ProviderException(e);
}
}
return total;
}
/**
* Wrap a {@code Key} using this Cipher's current encryption parameters.
*
@ -1243,6 +1377,11 @@ abstract class ChaCha20Cipher extends CipherSpi {
*/
int doFinal(byte[] in, int inOff, int inLen, byte[] out, int outOff)
throws ShortBufferException, AEADBadTagException, KeyException;
int doUpdate(ByteBuffer input, ByteBuffer output) throws
ShortBufferException, KeyException;
int doFinal(ByteBuffer input, ByteBuffer output) throws
ShortBufferException, KeyException, AEADBadTagException;
}
private final class EngineStreamOnly implements ChaChaEngine {
@ -1285,6 +1424,22 @@ abstract class ChaCha20Cipher extends CipherSpi {
int outOff) throws ShortBufferException, KeyException {
return doUpdate(in, inOff, inLen, out, outOff);
}
@Override
public int doUpdate(ByteBuffer input, ByteBuffer output) throws
ShortBufferException, KeyException {
byte[] data = new byte[input.remaining()];
input.get(data);
doUpdate(data, 0, data.length, data, 0);
output.put(data);
return data.length;
}
@Override
public int doFinal(ByteBuffer input, ByteBuffer output)
throws ShortBufferException, KeyException {
return doUpdate(input, output);
}
}
private final class EngineAEADEnc implements ChaChaEngine {
@ -1348,11 +1503,32 @@ abstract class ChaCha20Cipher extends CipherSpi {
aadDone = false;
return inLen + TAG_LENGTH;
}
@Override
public int doUpdate(ByteBuffer input, ByteBuffer output) throws
ShortBufferException, KeyException {
byte[] data = new byte[input.remaining()];
input.get(data);
doUpdate(data, 0, data.length, data, 0);
output.put(data);
return data.length;
}
@Override
public int doFinal(ByteBuffer input, ByteBuffer output) throws
ShortBufferException, KeyException {
int len = input.remaining();
byte[] data = new byte[len + TAG_LENGTH];
input.get(data, 0, len);
doFinal(data, 0, len, data, 0);
output.put(data);
return data.length;
}
}
private final class EngineAEADDec implements ChaChaEngine {
private final ByteArrayOutputStream cipherBuf;
private AEADBufferedStream cipherBuf = null;
private final byte[] tag;
@Override
@ -1364,20 +1540,32 @@ abstract class ChaCha20Cipher extends CipherSpi {
// size.
return (isFinal ?
Integer.max(Math.addExact((inLen - TAG_LENGTH),
cipherBuf.size()), 0) : 0);
getBufferedLength()), 0) : 0);
}
private void initBuffer(int len) {
if (cipherBuf == null) {
cipherBuf = new AEADBufferedStream(len);
}
}
private int getBufferedLength() {
if (cipherBuf != null) {
return cipherBuf.size();
}
return 0;
}
private EngineAEADDec() throws InvalidKeyException {
initAuthenticator();
initCounterValue = 1;
counter = initCounterValue;
cipherBuf = new ByteArrayOutputStream(CIPHERBUF_BASE);
tag = new byte[TAG_LENGTH];
}
@Override
public int doUpdate(byte[] in, int inOff, int inLen, byte[] out,
int outOff) {
int outOff) {
if (initialized) {
// If this is the first update since AAD updates, signal that
// we're done processing AAD info and pad the AAD to a multiple
@ -1389,6 +1577,7 @@ abstract class ChaCha20Cipher extends CipherSpi {
if (in != null) {
Objects.checkFromIndexSize(inOff, inLen, in.length);
initBuffer(inLen);
cipherBuf.write(in, inOff, inLen);
}
} else {
@ -1399,6 +1588,14 @@ abstract class ChaCha20Cipher extends CipherSpi {
return 0;
}
@Override
public int doUpdate(ByteBuffer input, ByteBuffer output) {
initBuffer(input.remaining());
cipherBuf.write(input);
return 0;
}
@Override
public int doFinal(byte[] in, int inOff, int inLen, byte[] out,
int outOff) throws ShortBufferException, AEADBadTagException,
@ -1406,7 +1603,7 @@ abstract class ChaCha20Cipher extends CipherSpi {
byte[] ctPlusTag;
int ctPlusTagLen;
if (cipherBuf.size() == 0 && inOff == 0) {
if (getBufferedLength() == 0) {
// No previous data has been seen before doFinal, so we do
// not need to hold any ciphertext in a buffer. We can
// process it directly from the "in" parameter.
@ -1415,10 +1612,11 @@ abstract class ChaCha20Cipher extends CipherSpi {
ctPlusTagLen = inLen;
} else {
doUpdate(in, inOff, inLen, out, outOff);
ctPlusTag = cipherBuf.toByteArray();
ctPlusTagLen = ctPlusTag.length;
ctPlusTag = cipherBuf.getBuffer();
inOff = 0;
ctPlusTagLen = cipherBuf.size();
cipherBuf.reset();
}
cipherBuf.reset();
// There must at least be a tag length's worth of ciphertext
// data in the buffered input.
@ -1436,19 +1634,80 @@ abstract class ChaCha20Cipher extends CipherSpi {
// Calculate and compare the tag. Only do the decryption
// if and only if the tag matches.
authFinalizeData(ctPlusTag, 0, ctLen, tag, 0);
long tagCompare = ((long)asLongView.get(ctPlusTag, ctLen) ^
authFinalizeData(ctPlusTag, inOff, ctLen, tag, 0);
long tagCompare = ((long)asLongView.get(ctPlusTag, ctLen + inOff) ^
(long)asLongView.get(tag, 0)) |
((long)asLongView.get(ctPlusTag, ctLen + Long.BYTES) ^
((long)asLongView.get(ctPlusTag, ctLen + inOff + Long.BYTES) ^
(long)asLongView.get(tag, Long.BYTES));
if (tagCompare != 0) {
throw new AEADBadTagException("Tag mismatch");
}
chaCha20Transform(ctPlusTag, 0, ctLen, out, outOff);
chaCha20Transform(ctPlusTag, inOff, ctLen, out, outOff);
aadDone = false;
return ctLen;
}
@Override
public int doFinal(ByteBuffer input, ByteBuffer output)
throws ShortBufferException, AEADBadTagException, KeyException {
int len;
int inLen = input.remaining();
byte[] ct = null, buf = null;
//buf = (getBufferedLength() == 0 ? null : cipherBuf.toByteArray());
int bufLen = 0;
// The length of cipher text and tag
int ctLen = getBufferedLength() + inLen;
if (ctLen < TAG_LENGTH) {
throw new AEADBadTagException("Input too short - need tag");
}
if (inLen < TAG_LENGTH) {
if (inLen > 0) {
doUpdate(input, output);
}
if (cipherBuf != null) {
ct = cipherBuf.getBuffer();
}
len = ctLen;
} else {
if (cipherBuf != null) {
buf = cipherBuf.getBuffer();
bufLen = cipherBuf.size();
}
ct = new byte[inLen];
input.get(ct, 0, inLen);
len = inLen;
}
doUpdate(null, 0, 0, null, 0);
// If there is an internal buffer, calculate its tag contribution.
if (buf != null) {
dataLen = authUpdate(buf, 0, bufLen);
}
// Complete tag calculation
len -= TAG_LENGTH;
authFinalizeData(ct, 0, len, tag, 0);
// Check tag
if ((((long) asLongView.get(ct, len) ^
(long) asLongView.get(tag, 0)) |
((long) asLongView.get(ct, len + Long.BYTES) ^
(long) asLongView.get(tag, Long.BYTES))) != 0) {
throw new AEADBadTagException("Tag mismatch");
}
// decrypt internal buffer in-place, then put it into the bytebuffer
if (buf != null) {
chaCha20Transform(buf, 0, bufLen, buf, 0);
output.put(buf, 0, bufLen);
}
// decrypt input buffer in-place, append it to the bytebuffer
chaCha20Transform(ct, 0, len, ct, 0);
output.put(ct, 0, len);
aadDone = false;
return ctLen - TAG_LENGTH;
}
}
public static final class ChaCha20Only extends ChaCha20Cipher {

View file

@ -40,8 +40,6 @@ import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.GCMParameterSpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteBuffer;
@ -249,7 +247,7 @@ abstract class GaloisCounterMode extends CipherSpi {
protected AlgorithmParameters engineGetParameters() {
GCMParameterSpec spec;
spec = new GCMParameterSpec(tagLenBytes * 8,
iv == null ? createIv(random) : iv.clone());
iv == null ? createIv(random) : iv); // iv.clone() not necessary
try {
AlgorithmParameters params =
AlgorithmParameters.getInstance("GCM",
@ -680,12 +678,12 @@ abstract class GaloisCounterMode extends CipherSpi {
final int blockSize;
// buffer for AAD data; if null, meaning update has been called
ByteArrayOutputStream aadBuffer = null;
AEADBufferedStream aadBuffer = null;
int sizeOfAAD = 0;
boolean aadProcessed = false;
// buffer data for crypto operation
ByteArrayOutputStream ibuffer = null;
AEADBufferedStream ibuffer = null;
// Original dst buffer if there was an overlap situation
ByteBuffer originalDst = null;
@ -736,7 +734,7 @@ abstract class GaloisCounterMode extends CipherSpi {
// Initialize internal data buffer, if not already.
void initBuffer(int len) {
if (ibuffer == null) {
ibuffer = new ByteArrayOutputStream(len);
ibuffer = new AEADBufferedStream(len);
}
}
@ -788,20 +786,6 @@ abstract class GaloisCounterMode extends CipherSpi {
}
}
/**
* The method takes two buffers to create one block of data. The
* difference with the other mergeBlock is this will calculate
* the bufLen from the existing 'buffer' length & offset
*
* This is only called when buffer length is less than a blockSize
* @return number of bytes used from 'in'
*/
int mergeBlock(byte[] buffer, int bufOfs, byte[] in, int inOfs,
int inLen, byte[] block) {
return mergeBlock(buffer, bufOfs, buffer.length - bufOfs, in,
inOfs, inLen, block);
}
/**
* The method takes two buffers to create one block of data
*
@ -822,7 +806,7 @@ abstract class GaloisCounterMode extends CipherSpi {
}
/**
* Continues a multi-part update of the Additional Authentication
* Continues a multipart update of the Additional Authentication
* Data (AAD), using a subset of the provided buffer. All AAD must be
* supplied before beginning operations on the ciphertext (via the
* {@code update} and {@code doFinal} methods).
@ -843,7 +827,7 @@ abstract class GaloisCounterMode extends CipherSpi {
if (aadBuffer == null) {
if (sizeOfAAD == 0 && !aadProcessed) {
aadBuffer = new ByteArrayOutputStream(len);
aadBuffer = new AEADBufferedStream(len);
} else {
// update has already been called
throw new IllegalStateException
@ -856,18 +840,17 @@ abstract class GaloisCounterMode extends CipherSpi {
// Feed the AAD data to GHASH, pad if necessary
void processAAD() {
if (aadBuffer != null) {
if (aadBuffer.size() > 0) {
byte[] aad = aadBuffer.toByteArray();
sizeOfAAD = aad.length;
int lastLen = aad.length % blockSize;
sizeOfAAD = aadBuffer.size();
if (sizeOfAAD > 0) {
byte[] aad = aadBuffer.getBuffer();
int lastLen = sizeOfAAD % blockSize;
if (lastLen != 0) {
ghash.update(aad, 0, aad.length - lastLen);
ghash.update(aad, 0, sizeOfAAD - lastLen);
byte[] padded = expandToOneBlock(aad,
aad.length - lastLen, lastLen, blockSize);
sizeOfAAD - lastLen, lastLen, blockSize);
ghash.update(padded);
} else {
ghash.update(aad);
ghash.update(aad, 0, sizeOfAAD);
}
}
aadBuffer = null;
@ -1147,7 +1130,7 @@ abstract class GaloisCounterMode extends CipherSpi {
// if there is enough data in the ibuffer and 'in', encrypt it.
if (bLen > 0) {
byte[] buffer = ibuffer.toByteArray();
byte[] buffer = ibuffer.getBuffer();
// number of bytes not filling a block
int remainder = blockSize - bLen;
@ -1167,7 +1150,7 @@ abstract class GaloisCounterMode extends CipherSpi {
}
}
// Encrypt the remaining blocks inside of 'in'
// Encrypt the remaining blocks inside 'in'
if (inLen >= PARALLEL_LEN) {
int r = GaloisCounterMode.implGCMCrypt(in, inOfs, inLen, out,
outOfs, out, outOfs, gctr, ghash);
@ -1223,7 +1206,8 @@ abstract class GaloisCounterMode extends CipherSpi {
// Check if there is enough 'src' and 'buffer' to fill a block
if (src.remaining() >= remainder) {
byte[] block = new byte[blockSize];
ByteBuffer buffer = ByteBuffer.wrap(ibuffer.toByteArray());
ByteBuffer buffer = ByteBuffer.wrap(ibuffer.getBuffer(),
0, ibuffer.size());
buffer.get(block, 0, bLen);
src.get(block, bLen, remainder);
len += op.update(ByteBuffer.wrap(block, 0, blockSize),
@ -1251,14 +1235,8 @@ abstract class GaloisCounterMode extends CipherSpi {
// Write the remaining bytes into the 'ibuffer'
if (srcLen > 0) {
initBuffer(srcLen);
byte[] b = new byte[srcLen];
src.get(b);
// remainder offset is based on original buffer length
try {
ibuffer.write(b);
} catch (IOException e) {
throw new RuntimeException(e);
}
ibuffer.write(src);
}
restoreDst(dst);
@ -1290,13 +1268,13 @@ abstract class GaloisCounterMode extends CipherSpi {
// process what is in the ibuffer
if (bLen > 0) {
byte[] buffer = ibuffer.toByteArray();
byte[] buffer = ibuffer.getBuffer();
// Make a block if the remaining ibuffer and 'in' can make one.
if (bLen + inLen >= blockSize) {
int r;
block = new byte[blockSize];
r = mergeBlock(buffer, 0, in, inOfs, inLen, block);
r = mergeBlock(buffer, 0, ibuffer.size(), in, inOfs, inLen, block);
inOfs += r;
inLen -= r;
op.update(block, 0, blockSize, out, outOfs);
@ -1353,7 +1331,8 @@ abstract class GaloisCounterMode extends CipherSpi {
if (len > 0) {
processed += doLastBlock(op,
(ibuffer == null || ibuffer.size() == 0) ? null :
ByteBuffer.wrap(ibuffer.toByteArray()), src, dst);
ByteBuffer.wrap(ibuffer.getBuffer(), 0,
ibuffer.size()), src, dst);
}
// release buffer if needed
@ -1427,9 +1406,10 @@ abstract class GaloisCounterMode extends CipherSpi {
tagLenBytes);
} else {
// tagOfs will be negative
byte[] buffer = ibuffer.toByteArray();
tagOfs = mergeBlock(buffer,
buffer.length - (tagLenBytes - inLen), in, inOfs, inLen,
byte[] buffer = ibuffer.getBuffer();
int ofs = ibuffer.size() - (tagLenBytes - inLen);
tagOfs = mergeBlock(buffer, ofs, ibuffer.size() - ofs,
in, inOfs, inLen,
tag) - tagLenBytes;
}
}
@ -1475,15 +1455,8 @@ abstract class GaloisCounterMode extends CipherSpi {
src.remaining(), null, 0);
src.position(src.limit());
} else {
byte[] b = new byte[src.remaining()];
src.get(b);
initBuffer(b.length);
try {
ibuffer.write(b);
} catch (IOException e) {
throw new ProviderException(
"Unable to add remaining input to the buffer", e);
}
initBuffer(src.remaining());
ibuffer.write(src);
}
}
return 0;
@ -1491,7 +1464,7 @@ abstract class GaloisCounterMode extends CipherSpi {
/**
* Use available data from ibuffer and 'in' to verify and decrypt the
* data. If the verification fails, the 'out' left to it's original
* data. If the verification fails, the 'out' left to its original
* values if crypto was in-place; otherwise 'out' is zeroed
*/
@Override
@ -1551,7 +1524,7 @@ abstract class GaloisCounterMode extends CipherSpi {
/**
* Use available data from ibuffer and 'src' to verify and decrypt the
* data. If the verification fails, the 'dst' left to it's original
* data. If the verification fails, the 'dst' left to its original
* values if crypto was in-place; otherwise 'dst' is zeroed
*/
@Override
@ -1568,7 +1541,8 @@ abstract class GaloisCounterMode extends CipherSpi {
// Check if ibuffer has data
if (getBufferedLength() != 0) {
buffer = ByteBuffer.wrap(ibuffer.toByteArray());
buffer = ByteBuffer.wrap(ibuffer.getBuffer(), 0,
ibuffer.size());
len += buffer.remaining();
}
@ -1684,7 +1658,7 @@ abstract class GaloisCounterMode extends CipherSpi {
}
if (bLen > 0) {
buffer = ibuffer.toByteArray();
buffer = ibuffer.getBuffer();
if (bLen >= PARALLEL_LEN) {
len = GaloisCounterMode.implGCMCrypt(buffer, 0, bLen,