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

        byte[] buffer = apdu.getBuffer();
        byte p1 = buffer[OFFSET_P1];
        byte p2 = buffer[OFFSET_P2];

        short offset = 0;
        
        if((byte)(p1 & MASK_SFI) == MASK_SFI) {
            byte sfi = (byte)(p1 & ~MASK_SFI);
            if(sfi >= 0x1F) {
                ISOException.throwIt(SW_INCORRECT_P1P2);
            }
            short fid = Util.makeShort((byte)0x00, sfi);
            if (fileSystem.getFile(fid) != null) {
                selectedFile = fid;
                volatileState[0] |= FILE_SELECTED;
            }else{
                setNoFileSelected();
                ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
            }
            offset = (short)(p2 & 0xFF);
        }else{
            if(!hasFileSelected()) {
                ISOException.throwIt(SW_CONDITIONS_NOT_SATISFIED);
            }
            offset = Util.makeShort(p1, p2);
        }

        byte[] file = fileSystem.getFile(selectedFile);
        // FIXME is this check redundant?
        if (file == null) {
            ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
        }

        short len;
        short fileSize = fileSystem.getFileSize(selectedFile);

        len = SmartIDUtil.min((short) (buffer.length - 37),
                (short) (fileSize - offset));
        // FIXME: 37 magic
        len = SmartIDUtil.min(len, (short) buffer.length);
        len = SmartIDUtil.min(le, len);
        short bufferOffset = 0;
        if (protectedApdu) {
            bufferOffset = crypto.getApduBufferOffset(len);
        }
        Util.arrayCopyNonAtomic(file, offset, buffer, bufferOffset, len);

        return len;
    }