in src/main/java/org/apache/commons/crypto/cipher/OpenSslGaloisCounterMode.java [62:117]
public int doFinal(final byte[] input, final int inputOffset, final int inputLen, final byte[] output, final int outputOffset)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
checkState();
processAAD();
final int outputLength = output.length;
int len;
if (this.cipherMode == OpenSsl.DECRYPT_MODE) {
// if GCM-DECRYPT, we have to handle the buffered input
// and the retrieve the trailing tag from input
int inputOffsetFinal = inputOffset;
int inputLenFinal = inputLen;
final byte[] inputFinal;
if (inBuffer != null && inBuffer.size() > 0) {
inBuffer.write(input, inputOffset, inputLen);
inputFinal = inBuffer.toByteArray();
inputOffsetFinal = 0;
inputLenFinal = inputFinal.length;
inBuffer.reset();
} else {
inputFinal = input;
}
if (inputFinal.length < getTagLen()) {
throw new AEADBadTagException("Input too short - need tag");
}
final int inputDataLen = inputLenFinal - getTagLen();
len = OpenSslNative.updateByteArray(context, inputFinal, inputOffsetFinal,
inputDataLen, output, outputOffset, outputLength - outputOffset);
// set tag to EVP_Cipher for integrity verification in doFinal
final ByteBuffer tag = ByteBuffer.allocate(getTagLen());
tag.put(input, input.length - getTagLen(), getTagLen());
tag.flip();
evpCipherCtxCtrl(context, OpenSslEvpCtrlValues.AEAD_SET_TAG.getValue(), getTagLen(), tag);
} else {
len = OpenSslNative.updateByteArray(context, input, inputOffset,
inputLen, output, outputOffset, outputLength - outputOffset);
}
len += OpenSslNative.doFinalByteArray(context, output, outputOffset + len,
outputLength - outputOffset - len);
// Keep the similar behavior as JCE, append the tag to end of output
if (this.cipherMode == OpenSsl.ENCRYPT_MODE) {
final ByteBuffer tag;
tag = ByteBuffer.allocate(getTagLen());
evpCipherCtxCtrl(context, OpenSslEvpCtrlValues.AEAD_GET_TAG.getValue(), getTagLen(), tag);
tag.get(output, outputLength - getTagLen(), getTagLen());
len += getTagLen();
}
return len;
}