Android Open Source - MifareClassicTool Access Condition Decoder






From Project

Back to project page MifareClassicTool.

License

The source code is released under:

GNU General Public License

If you think the Android project MifareClassicTool listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2013 Gerhard Klostermeier//w  ww  .j av a  2 s . c o m
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


package de.syss.MifareClassicTool.Activities;

import android.os.Bundle;
import android.text.SpannableString;
import android.util.Log;
import android.widget.TableLayout;
import android.widget.TableLayout.LayoutParams;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.TextView.BufferType;
import de.syss.MifareClassicTool.Common;
import de.syss.MifareClassicTool.Common.Operations;
import de.syss.MifareClassicTool.R;

/**
 * Display the Mifare Access Conditions in a way a user can read.
 * NXP has PDFs describing what access conditions are.
 * Google something like "nxp mifare classic access conditions",
 * if you want to have a closer look.
 * This Activity will be shown from the {@link DumpEditor}, if the user
 * clicks the corresponding menu item.
 * @author Gerhard Klostermeier
 */
public class AccessConditionDecoder extends BasicActivity {

    public final static String EXTRA_AC =
            "de.syss.MifareClassicTool.Activity.AC";

    private static final String LOG_TAG =
            AccessConditionDecoder.class.getSimpleName();

    private TableLayout mLayout;

    /**
     * Get access conditions from Intent and initialize Activity to
     * displaying them. If there is no Intent with
     * {@link #EXTRA_AC}, the Activity will be exited.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_access_condition_decoder);

        if (getIntent().hasExtra(EXTRA_AC)) {
            mLayout = (TableLayout) findViewById(
                    R.id.tableLayoutAccessConditionDecoder);
            String[] accessConditions =
                getIntent().getStringArrayExtra(EXTRA_AC);
            for (int j = 0; j < accessConditions.length; j=j+2) {
                boolean hasMoreThan4Blocks = false;
                if (accessConditions[j+1].startsWith("*")) {
                    hasMoreThan4Blocks = true;
                    accessConditions[j+1] = accessConditions[j+1].substring(1);
                }

                // b6 = bAC[0], b7 = bAC[1], ...
                byte[] bAC = Common.hexStringToByteArray(accessConditions[j+1]);

                // acMatrix[C1-C3][Block1-Block3 + Sector Trailer]
                byte[][] acMatrix = Common.acBytesToACMatrix(bAC);
                if (acMatrix != null) {
                    String sectorNumber = accessConditions[j].split(": ")[1];
                    addSectorAC(acMatrix, getString(R.string.text_sector)
                            + ": " + sectorNumber, hasMoreThan4Blocks);
                }
            }
        } else {
            Log.d(LOG_TAG, "There were no access conditions in intent.");
            finish();
        }
    }

    /**
     * Add full access condition information about one sector to the layout
     * table. (This method will trigger
     * {@link #addBlockAC(byte[][], boolean)} and
     * {@link #addSectorTrailerAC(byte[][])}
     * @param acMatrix Matrix of access conditions bits (C1-C3) where the first
     * dimension is the "C" parameter (C1-C3, Index 0-2) and the second
     * dimension is the block number
     * (Block0-Block2 + Sector Trailer, Index 0-3).
     * @param sectorHeader The sector header to display (e.g. "Sector: 0").
     * @param hasMoreThan4Blocks True for the last 8 sectors
     * of a Mifare Classic 4K tag.
     * @see #addBlockAC(byte[][], boolean)
     * @see #addSectorTrailerAC(byte[][])
     */
    private void addSectorAC(byte[][] acMatrix, String sectorHeader,
            boolean hasMoreThan4Blocks) {
        // Add sector header.
        TextView header = new TextView(this);
        header.setText(Common.colorString(sectorHeader,
                getResources().getColor(R.color.blue)),
                BufferType.SPANNABLE);
        TableRow tr = new TableRow(this);
        tr.setLayoutParams(new LayoutParams(
                LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT));
        tr.addView(header);
        mLayout.addView(tr, new LayoutParams(
                LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT));
        // Add Block 0-2.
        addBlockAC(acMatrix, hasMoreThan4Blocks);
        // Add Sector Trailer.
        addSectorTrailerAC(acMatrix);
    }

    /**
     * Add full access condition information of the 3 data blocks to the table.
     * @param acMatrix A matrix of access conditions bits as generated by
     * {@link Common#acBytesToACMatrix(byte[])}.
     * @param hasMoreThan4Blocks True for the last 8 sectors
     * of a Mifare Classic 4K tag, False otherwise.
     */
    private void addBlockAC(byte[][] acMatrix, boolean hasMoreThan4Blocks) {
        boolean isKeyBReadable = Common.isKeyBReadable(
                acMatrix[0][3], acMatrix[1][3], acMatrix[2][3]);

        for (int i = 0; i < 3; i++) {
            byte c1 = acMatrix[0][i];
            byte c2 = acMatrix[1][i];
            byte c3 = acMatrix[2][i];
            // Create row and header.
            TableRow tr = new TableRow(this);
            String blockHeader = "";
            if (hasMoreThan4Blocks) {
                blockHeader = getString(R.string.text_block)
                        + ": " + (i*4+i) + "-" + (i*4+4+i);
            } else {
                blockHeader = getString(R.string.text_block) + ": " + i;
            }
            tr.setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT));
            // Create cells.
            TextView location = new TextView(this);
            location.setText(blockHeader);
            TextView read = new TextView(this);
            TextView write = new TextView(this);
            TextView incr = new TextView(this);
            TextView decr = new TextView(this);

            // Set cell texts to colored permissions.
            read.setText(getColoredPermissionText(c1, c2, c3,
                    Operations.Read, false, isKeyBReadable));
            write.setText(getColoredPermissionText(c1, c2, c3,
                    Operations.Write, false, isKeyBReadable));
            incr.setText(getColoredPermissionText(c1, c2, c3,
                    Operations.Increment, false, isKeyBReadable));
            decr.setText(getColoredPermissionText(c1, c2, c3,
                    Operations.DecTransRest, false, isKeyBReadable));

            // Add cells to row.
            tr.addView(location);
            tr.addView(read);
            tr.addView(write);
            tr.addView(incr);
            tr.addView(decr);
            // Add row to layout.
            mLayout.addView(tr, new LayoutParams(
                    LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT));
        }
    }

    /**
     * Add full access condition information of the sector trailer (last block)
     * to the table.
     * @param acMatrix A matrix of access conditions bits as generated by
     * {@link Common#acBytesToACMatrix(byte[])}.
     * (Block0-Block2 + Sector Trailer, Index 0-3).
     */
    private void addSectorTrailerAC(byte[][] acMatrix) {
        byte c1 = acMatrix[0][3];
        byte c2 = acMatrix[1][3];
        byte c3 = acMatrix[2][3];
        // Create rows.
        TextView[] read = new TextView[3];
        TextView[] write = new TextView[3];
        for (int i = 0; i < 3; i++) {
            read[i] = new TextView(this);
            write[i] = new TextView(this);
        }

        // Set row texts to colored permissions.
        read[0].setText(getColoredPermissionText(c1, c2, c3,
                Operations.ReadKeyA, true, false));
        write[0].setText(getColoredPermissionText(c1, c2, c3,
                Operations.WriteKeyA, true, false));
        read[1].setText(getColoredPermissionText(c1, c2, c3,
                Operations.ReadAC, true, false));
        write[1].setText(getColoredPermissionText(c1, c2, c3,
                Operations.WriteAC, true, false));
        read[2].setText(getColoredPermissionText(c1, c2, c3,
                Operations.ReadKeyB, true, false));
        write[2].setText(getColoredPermissionText(c1, c2, c3,
                Operations.WriteKeyB, true, false));

        // Add rows to layout.
        String[] headers = new String[] {"Key A:", "AC Bits:", "Key B:"};
        for (int i = 0; i < 3; i++) {
            TableRow tr = new TableRow(this);
            tr.setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT));
            TextView location = new TextView(this);
            location.setText(headers[i]);
            tr.addView(location);
            tr.addView(read[i]);
            tr.addView(write[i]);
            mLayout.addView(tr, new LayoutParams(
                    LayoutParams.MATCH_PARENT,
                    LayoutParams.WRAP_CONTENT));
        }
    }

    /**
     * A helper function for {@link #addBlockAC(byte[][], boolean)} and
     * {@link #addSectorTrailerAC(byte[][])} creating a colored text
     * depending on the Access Conditions and the requested operation
     * ({@link Operations}).
     * @param c1 Access Condition byte "C1"
     * @param c2 Access Condition byte "C2"
     * @param c3 Access Condition byte "C3"
     * @param op Operation on the tag (see {@link Operations}).
     * @param isSectorTrailer True if it is a Sector Trailer, False otherwise.
     * @param isKeyBReadable True if key B is readable, False otherwise.
     * @return A colored text depending on the return value of
     * {@link Common#getOperationInfoForBlock(byte, byte, byte, Operations,
     * boolean, boolean)}. On Error an empty string will be returned.
     */
    private SpannableString getColoredPermissionText(byte c1, byte c2, byte c3,
            Operations op, boolean isSectorTrailer,
            boolean isKeyBReadable) {
        switch (Common.getOperationInfoForBlock(c1, c2, c3, op,
                isSectorTrailer, isKeyBReadable)) {
        case 0:
            // Never.
            return Common.colorString(getString(R.string.text_never),
                    getResources().getColor(R.color.orange));
        case 1:
            // Key A.
            return Common.colorString(getString(R.string.text_key_a),
                    getResources().getColor(R.color.yellow));
        case 2:
            // Key B.
            return Common.colorString(getString(R.string.text_key_b),
                    getResources().getColor(R.color.yellow));
        case 3:
            // Key A|B.
            return Common.colorString(getString(R.string.text_key_ab),
                    getResources().getColor(R.color.light_green));
        case 4:
            // Access Condition Error.
            return Common.colorString(getString(R.string.text_ac_error),
                    getResources().getColor(R.color.red));
        default:
            // Error:
            return new SpannableString("");
        }
    }
}




Java Source Code List

de.syss.MifareClassicTool.Common.java
de.syss.MifareClassicTool.MCDiffUtils.java
de.syss.MifareClassicTool.MCReader.java
de.syss.MifareClassicTool.Activities.AccessConditionDecoder.java
de.syss.MifareClassicTool.Activities.AccessConditionTool.java
de.syss.MifareClassicTool.Activities.BasicActivity.java
de.syss.MifareClassicTool.Activities.DiffTool.java
de.syss.MifareClassicTool.Activities.DumpEditor.java
de.syss.MifareClassicTool.Activities.FileChooser.java
de.syss.MifareClassicTool.Activities.HelpAndInfo.java
de.syss.MifareClassicTool.Activities.HexToAscii.java
de.syss.MifareClassicTool.Activities.IActivityThatReactsToSave.java
de.syss.MifareClassicTool.Activities.KeyEditor.java
de.syss.MifareClassicTool.Activities.KeyMapCreator.java
de.syss.MifareClassicTool.Activities.MainMenu.java
de.syss.MifareClassicTool.Activities.Preferences.java
de.syss.MifareClassicTool.Activities.ReadTag.java
de.syss.MifareClassicTool.Activities.TagInfoTool.java
de.syss.MifareClassicTool.Activities.ValueBlockTool.java
de.syss.MifareClassicTool.Activities.ValueBlocksToInt.java
de.syss.MifareClassicTool.Activities.WriteTag.java
de.syss.MifareClassicTool.Activities.package-info.java
de.syss.MifareClassicTool.package-info.java