public int doFinal()

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;
    }