short wrapResponseAPDU(byte[] ssc, APDU aapdu,
            short plaintextOffset, short plaintextLen, short sw1sw2) {
        byte[] apdu = aapdu.getBuffer();
        short apdu_p = 0;
        // smallest multiple of 8 strictly larger than plaintextLen
        short do87DataLen = SmartIDUtil.lengthWithPadding(plaintextLen);
        // for 0x01 marker (indicating padding is used)
        do87DataLen++;
        short do87DataLenBytes = (short) (do87DataLen > 0xff ? 2 : 1);
        short do87HeaderBytes = getApduBufferOffset(plaintextLen);
        short do87Bytes = (short) (do87HeaderBytes + do87DataLen - 1); // 0x01
                                                                        // is
                                                                        // counted
                                                                        // twice
        boolean hasDo87 = plaintextLen > 0;

        incrementSSC(ssc);

        short ciphertextLength = 0;
        short possiblyPaddedPlaintextLength = 0;
        if (hasDo87) {
            // put ciphertext in proper position.
            possiblyPaddedPlaintextLength = encryptInit(PAD_INPUT, apdu,
                    plaintextOffset, plaintextLen);
            ciphertextLength = encryptFinal(apdu, plaintextOffset,
                    possiblyPaddedPlaintextLength, apdu, do87HeaderBytes);
        }
        // sanity check
        // note that this check
        // (possiblyPaddedPlaintextLength != (short)(do87DataLen -1))
        // does not always hold because some algs do the padding in the final,
        // some in the init.
        if (hasDo87 && (((short) (do87DataLen - 1) != ciphertextLength)))
            ISOException.throwIt((short) 0x6d66);

        if (hasDo87) {
            // build do87
            apdu[apdu_p++] = (byte) 0x87;
            if (do87DataLen < 0x80) {
                apdu[apdu_p++] = (byte) do87DataLen;
            } else {
                apdu[apdu_p++] = (byte) (0x80 + do87DataLenBytes);
                for (short i = (short) (do87DataLenBytes - 1); i >= 0; i--) {
                    apdu[apdu_p++] = (byte) ((do87DataLen >>> (i * 8)) & 0xff);
                }
            }
            apdu[apdu_p++] = 0x01;
        }

        if (hasDo87) {
            apdu_p = do87Bytes;
        }

        // build do99
        apdu[apdu_p++] = (byte) 0x99;
        apdu[apdu_p++] = 0x02;
        Util.setShort(apdu, apdu_p, sw1sw2);
        apdu_p += 2;

        // calculate and write mac
        initMac(Signature.MODE_SIGN);
        updateMac(ssc, (short) 0, (short) ssc.length);
        createMacFinal(apdu, (short) 0, apdu_p, apdu, (short) (apdu_p + 2));

        // write do8e
        apdu[apdu_p++] = (byte) 0x8e;
        apdu[apdu_p++] = 0x08;
        apdu_p += 8; // for mac written earlier

        // Reset the secure messaging keys after successful EAC Chip Authentication
        if (eacChangeKeys[0]) {
            eacChangeKeys[0] = false;
            keyStore.setSecureMessagingKeys(keyStore.tmpKeys, (short) 0,
                    keyStore.tmpKeys, (short) 16);
            Util.arrayFillNonAtomic(keyStore.tmpKeys, (short) 0, (short) 32,
                    (byte) 0x00);
            Util.arrayFillNonAtomic(ssc, (short) 0, (short) ssc.length,
                    (byte) 0x00);
        }
        return apdu_p;
    }