in src/main/java/org/apache/commons/crypto/cipher/OpenSslGaloisCounterMode.java [120:196]
public int doFinal(final ByteBuffer input, final ByteBuffer output)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
checkState();
processAAD();
int totalLen = 0;
int len;
if (this.cipherMode == OpenSsl.DECRYPT_MODE) {
final ByteBuffer tag = ByteBuffer.allocate(getTagLen());
// if GCM-DECRYPT, we have to handle the buffered input
// and the retrieve the trailing tag from input
if (inBuffer != null && inBuffer.size() > 0) {
final byte[] inputBytes = new byte[input.remaining()];
input.get(inputBytes, 0, inputBytes.length);
inBuffer.write(inputBytes, 0, inputBytes.length);
final byte[] inputFinal = inBuffer.toByteArray();
inBuffer.reset();
if (inputFinal.length < getTagLen()) {
throw new AEADBadTagException("Input too short - need tag");
}
len = OpenSslNative.updateByteArrayByteBuffer(context, inputFinal, 0,
inputFinal.length - getTagLen(),
output, output.position(), output.remaining());
// retrieve tag
tag.put(inputFinal, inputFinal.length - getTagLen(), getTagLen());
} else {
// if no buffered input, just use the input directly
if (input.remaining() < getTagLen()) {
throw new AEADBadTagException("Input too short - need tag");
}
len = OpenSslNative.update(context, input, input.position(),
input.remaining() - getTagLen(), output, output.position(),
output.remaining());
input.position(input.position() + len);
// retrieve tag
tag.put(input);
}
tag.flip();
// set tag to EVP_Cipher for integrity verification in doFinal
evpCipherCtxCtrl(context, OpenSslEvpCtrlValues.AEAD_SET_TAG.getValue(),
getTagLen(), tag);
} else {
len = OpenSslNative.update(context, input, input.position(),
input.remaining(), output, output.position(),
output.remaining());
input.position(input.limit());
}
totalLen += len;
output.position(output.position() + len);
len = OpenSslNative.doFinal(context, output, output.position(),
output.remaining());
output.position(output.position() + len);
totalLen += 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);
output.put(tag);
totalLen += getTagLen();
}
return totalLen;
}