private short processInternalAuthenticate(APDU apdu, boolean protectedApdu) {
        if (!hasInternalAuthenticationKeys() ||
                (hasMutualAuthenticationKeys() && (!protectedApdu || !hasMutuallyAuthenticated()))) {
            ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
        }

        short buffer_p = (short) (OFFSET_CDATA & 0xff);
        short hdr_offset = 0;
        if (protectedApdu) {
            hdr_offset = crypto.getApduBufferOffset((short) 128);
        }
        short hdr_len = 1;
        short m1_len = 106; // whatever
        short m1_offset = (short) (hdr_offset + hdr_len);
        short m2_len = 8;
        short m2_offset = (short) (m1_offset + m1_len);
        // we will write the hash over m2
        short m1m2hash_offset = (short) (m1_offset + m1_len);
        short m1m2hash_len = 20;
        short trailer_offset = (short) (m1m2hash_offset + m1m2hash_len);
        short trailer_len = 1;

        byte[] buffer = apdu.getBuffer();
        short bytesLeft = (short) (buffer[OFFSET_LC] & 0x00FF);

        if (bytesLeft != m2_len)
            ISOException.throwIt(SW_WRONG_LENGTH);

        // put m2 in place
        Util.arrayCopyNonAtomic(buffer, buffer_p, buffer, m2_offset, m2_len);

        // write some random data of m1_len
        // randomData.generateData(buffer, m1_offset, m1_length);
        for (short i = m1_offset; i < (short) (m1_offset + m1_len); i++) {
            buffer[i] = 0;
        }

        crypto.shaDigest.doFinal(buffer, m1_offset, (short) (m1_len + m2_len), buffer,
                m1m2hash_offset);
        crypto.shaDigest.reset();

        // write trailer
        buffer[trailer_offset] = (byte) 0xbc;

        // write header
        buffer[hdr_offset] = (byte) 0x6a;

        // encrypt the whole buffer with our AA private key
        short plaintext_len = (short) (hdr_len + m1_len + m1m2hash_len + trailer_len);
        // sanity check
        if (plaintext_len != 128) {
            ISOException.throwIt(SW_INTERNAL_ERROR);
        }
        crypto.rsaCiph.init(keyStore.rsaPrivateKey, Cipher.MODE_ENCRYPT);
        short ciphertext_len = crypto.rsaCiph.doFinal(buffer, hdr_offset,
                plaintext_len, buffer, hdr_offset);
        // sanity check
        if (ciphertext_len != 128) {
            ISOException.throwIt(SW_INTERNAL_ERROR);
        }

        return ciphertext_len;
    }