Package org.nfctools.mf.block

Source Code of org.nfctools.mf.block.TrailerBlock

/**
* Copyright 2011-2012 Adrian Stabiszewski, as@nfctools.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.nfctools.mf.block;

import org.nfctools.mf.MfConstants;
import org.nfctools.mf.MfException;
import org.nfctools.mf.classic.Key;

public class TrailerBlock extends Block {

  private static final int KEY_LENGTH = 6;

  private static final int KEY_A_INDEX = 0;
  private static final int KEY_B_INDEX = 10;
  private static final int GPB_INDEX = 9;
  private static final int ACCESS_CONDITIONS_INDEX = 6;

  public TrailerBlock() {
    super(new byte[MfConstants.BYTES_PER_BLOCK], BLOCK_TYPE_TRAIL);
    try {
      setAccessConditions(MfConstants.TRANSPORT_ACCESS_CONDITIONS);
      setKey(Key.A, MfConstants.TRANSPORT_KEY);
      setKey(Key.B, MfConstants.TRANSPORT_KEY);
      setGeneralPurposeByte(MfConstants.TRANSPORT_GPB);
    }
    catch (MfException e) {
    }
  }

  public TrailerBlock(byte data[]) throws MfException {
    super(data, BLOCK_TYPE_TRAIL);
    if (!validAccessConditions(getAccessConditions())) {
      throw new MfException("illegal trailer block");
    }
  }

  @Override
  public TrailerBlock clone() {
    try {
      byte[] cloneData = new byte[data.length];
      System.arraycopy(data, 0, cloneData, 0, data.length);
      return new TrailerBlock(cloneData);
    }
    catch (MfException e) {
      throw new RuntimeException(e);
    }
  }

  public byte[] getKey(Key key) {
    byte[] keyValue = new byte[6];
    if (key == Key.A) {
      System.arraycopy(data, KEY_A_INDEX, keyValue, 0, KEY_LENGTH);
    }
    else {
      System.arraycopy(data, KEY_B_INDEX, keyValue, 0, KEY_LENGTH);
    }
    return keyValue;
  }

  public void setKey(Key key, byte[] keyValue) {
    if (key == Key.A) {
      System.arraycopy(keyValue, 0, data, KEY_A_INDEX, KEY_LENGTH);
    }
    else {
      System.arraycopy(keyValue, 0, data, KEY_B_INDEX, KEY_LENGTH);
    }
  }

  public byte getGeneralPurposeByte() {
    return data[GPB_INDEX];
  }

  public void setGeneralPurposeByte(byte gpb) {
    data[GPB_INDEX] = gpb;
  }

  public byte[] getAccessConditions() {
    byte[] acValue = new byte[3];
    System.arraycopy(data, ACCESS_CONDITIONS_INDEX, acValue, 0, acValue.length);
    return acValue;
  }

  public void setAccessConditions(byte[] acValue) throws MfException {
    if (validAccessConditions(acValue))
      System.arraycopy(acValue, 0, data, ACCESS_CONDITIONS_INDEX, acValue.length);
    else
      throw new MfException("illegal access conditions");
  }

  public static boolean validAccessConditions(byte[] acValue) {
    if (acValue.length != 3)
      return false;

    if ((((acValue[0] ^ 0xf0) >>> 4) & 0x0f) != (acValue[2] & 0x0f)) {
      return false;
    }

    if (((acValue[0] ^ 0x0f) & 0x0f) != ((acValue[1] >>> 4) & 0xf)) {
      return false;
    }

    if (((acValue[1] ^ 0x0f) & 0x0f) != ((acValue[2] >>> 4) & 0xf)) {
      return false;
    }
    return true;
  }

  public boolean isKeyBReadable() {
    int accessBits = extractAccesBitsForBlock(3);
    return accessBits == 0 || accessBits == 1 || accessBits == 2;
  }

  public boolean canWriteDataBlock(Key key, int dataArea) {
    int accessBits = extractAccesBitsForBlock(dataArea);
    if (Key.A.equals(key)) {
      return accessBits == 0;
    }
    else {
      return accessBits == 4 || accessBits == 3 || accessBits == 6 || (accessBits == 0 && !isKeyBReadable());
    }
  }

  public boolean canWriteTrailerBlock(Key key) {
    int accessBits = extractAccesBitsForBlock(3);
    if (Key.A.equals(key)) { // Simplified verification
      return accessBits == 1;
    }
    else {
      return accessBits == 3;
    }
  }

  private int extractAccesBitsForBlock(int blockId) {
    int accessBits = ((data[ACCESS_CONDITIONS_INDEX] >> blockId) & 0x01) << 2;
    accessBits |= ((data[ACCESS_CONDITIONS_INDEX + 2] >> blockId) & 0x01) << 1;
    accessBits |= ((data[ACCESS_CONDITIONS_INDEX + 1] >> blockId) & 0x01);

    int bitC2 = accessBits & 0x02;

    int inverted = (accessBits ^ 0x07);

    return (inverted & 0x05) | bitC2;

  }
}
TOP

Related Classes of org.nfctools.mf.block.TrailerBlock

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.