Example #1
0
  /* input data is supposed to have been validaded before */
  public static short GetBERTLVDataLen(byte[] buf, short offset, short len) {
    short size = 0;
    short sizeforsize = 0;
    short i = 1;

    if ((buf[offset] & 0x1F) != 0x1F) {
      // simplified tag
    } else {
      // tag start with all 5 last bits to 1
      // skip the tag
      while (((buf[(short) (offset + i)] & 0x80) != 0) && ((short) (i + offset)) < len) {
        i++;
      }
      // pass the last byte of the tag
      i += 1;
    }
    // check the size
    if ((buf[(short) (offset + i)] & 0x80) != 0) {
      // size encoded in many bytes
      sizeforsize = (short) (buf[(short) (offset + i)] & 0x7F);
      if (sizeforsize > 2) {
        // more than two bytes for encoding => not something than we can handle
        return 0;
      } else if (sizeforsize == 1) {
        size = Util.makeShort((byte) 0, buf[(short) (offset + i + 1)]);
      } else if (sizeforsize == 2) {
        size = Util.getShort(buf, (short) (offset + i + 1));
      }
    } else {
      // size encode in one byte
      size = Util.makeShort((byte) 0, buf[(short) (offset + i)]);
    }
    return size;
  }
Example #2
0
  /* returns 0 or the size of the BERTLV structure */
  public static short CheckBERTLV(byte[] buf, short offset, short len) {
    short size = 0;
    short sizeforsize = 0;
    short i = 1;
    short totalsize = 0;

    if ((buf[offset] & 0x1F) != 0x1F) {
      // simplified tag
    } else {
      // tag start with all 5 last bits to 1
      // skip the tag
      while (((buf[(short) (offset + i)] & 0x80) != 0) && i < len) {
        i++;
      }
      // pass the last byte of the tag
      i += 1;
    }
    if ((short) (i + 1) > len) {
      return 0;
    }
    // check the size
    if ((buf[(short) (offset + i)] & 0x80) != 0) {
      // size encoded in many bytes
      sizeforsize = (short) (buf[(short) (offset + i)] & 0x7F);
      if ((short) (i + 1 + sizeforsize) > len) {
        return 0;
      }
      if (sizeforsize > (short) 2) {
        // more than two bytes for encoding => not something than we can handle
        return 0;
      } else if (sizeforsize == (short) 1) {
        if ((short) (offset + i + 1 + sizeforsize) > len) {
          return 0;
        }
        size = Util.makeShort((byte) 0, buf[(short) (offset + i + 1)]);
      } else if (sizeforsize == 2) {
        totalsize = (short) (i + 1 + sizeforsize + size);
        if ((short) (offset + i + 1 + sizeforsize) > len) {
          return (short) 0;
        }
        size = Util.getShort(buf, (short) (offset + i + 1));
      }
    } else {
      // size encode in one byte
      size = Util.makeShort((byte) 0, buf[(short) (offset + i)]);
    }
    totalsize = (short) (i + 1 + sizeforsize + size);
    if (totalsize < (short) 240 && (short) (offset + totalsize) > len) {
      return (short) 0;
    }
    return totalsize;
  }
Example #3
0
 /** Process the WRITE BINARY Instruction (0xD0). ISO7816-4 Section 7.2.4 */
 private void processWriteBinary(APDU apdu) throws ISOException {
   if (state != STATE_INITIAL) {
     ISOException.throwIt(SW_INS_NOT_SUPPORTED);
   }
   byte[] buf = apdu.getBuffer();
   byte p1 = buf[OFFSET_P1];
   byte p2 = buf[OFFSET_P2];
   short offset = 0;
   short ef = -1;
   if ((byte) (p1 & MASK_SFI) == MASK_SFI) {
     byte sfi = (byte) (p1 | ~MASK_SFI);
     if (sfi >= 0x1F) {
       ISOException.throwIt(SW_INCORRECT_P1P2);
     }
     ef = fileSystem.findCurrentSFI(sfi);
     if (ef == -1) {
       ISOException.throwIt(SW_FILE_NOT_FOUND);
     }
     ef = fileSystem.fileStructure[ef];
     offset = unsigned(p2);
   } else {
     ef = fileSystem.getCurrentIndex();
     if (fileSystem.getFile(ef) == null) {
       ISOException.throwIt(SW_COMMAND_NOT_ALLOWED);
     }
     offset = Util.makeShort(p1, p2);
   }
   byte[] file = fileSystem.getFile(ef);
   short lc = unsigned(buf[OFFSET_LC]);
   if ((short) (offset + lc) > file.length) {
     ISOException.throwIt(SW_WRONG_LENGTH);
   }
   apdu.setIncomingAndReceive();
   Util.arrayCopyNonAtomic(buf, OFFSET_CDATA, file, offset, lc);
 }
Example #4
0
 /**
  * Process the READ BINARY instruction (0xB0) ISO7816-4 Section 7.2.3
  *
  * <p>We handle only the INS == 0xB0 case.
  */
 private void processReadBinary(APDU apdu) {
   if (state != STATE_PERSONALISED) {
     ISOException.throwIt(SW_CONDITIONS_NOT_SATISFIED);
   }
   byte[] buf = apdu.getBuffer();
   byte p1 = buf[OFFSET_P1];
   byte p2 = buf[OFFSET_P2];
   short offset = 0;
   short ef = -1;
   if ((byte) (p1 & MASK_SFI) == MASK_SFI) {
     byte sfi = (byte) (p1 & ~MASK_SFI);
     if (sfi >= 0x1F) {
       ISOException.throwIt(SW_INCORRECT_P1P2);
     }
     ef = fileSystem.findCurrentSFI(sfi);
     if (ef == -1) {
       ISOException.throwIt(SW_FILE_NOT_FOUND);
     }
     ef = fileSystem.fileStructure[ef];
     offset = unsigned(p2);
   } else {
     ef = fileSystem.getCurrentIndex();
     if (fileSystem.getFile(ef) == null) {
       ISOException.throwIt(SW_COMMAND_NOT_ALLOWED);
     }
     offset = Util.makeShort(p1, p2);
   }
   byte[] file = fileSystem.getFile(ef);
   if (offset > file.length) {
     ISOException.throwIt(SW_INCORRECT_P1P2);
   }
   if (fileSystem.getPerm(ef) == FileSystem.PERM_PIN && !pin.isValidated()) {
     ISOException.throwIt(SW_SECURITY_STATUS_NOT_SATISFIED);
   }
   short le = apdu.setOutgoing();
   if (le == 0 || le == 256) {
     le = (short) (file.length - offset);
     if (le > 256) le = 256;
   }
   boolean eof = false;
   if ((short) (file.length - offset) < le) {
     le = (short) (file.length - offset);
     eof = true;
   }
   apdu.setOutgoingLength(le);
   apdu.sendBytesLong(file, offset, le);
   if (eof) {
     ISOException.throwIt(SW_END_OF_FILE);
   }
 }
Example #5
0
 private short findEntryPath(short start, byte[] path, short offset, short length)
     throws FileNotFoundException {
   try {
     if (length == 0) {
       return start;
     }
     short id = Util.makeShort(path[offset], path[(short) (offset + 1)]);
     start = findEntryRelative(start, id);
     offset += 2;
     length = (short) (length - 2);
     return findEntryPath(start, path, offset, length);
   } catch (ArrayIndexOutOfBoundsException aioobe) {
     throw fnfe;
   }
 }
Example #6
0
  /** Process the SELECT (file) instruction (0xA4) ISO7816-4 Section 7.1.1 */
  private void processSelectFile(APDU apdu) {
    byte[] buf = apdu.getBuffer();
    byte p1 = buf[OFFSET_P1];
    // byte p2 = buf[OFFSET_P2];
    short lc = unsigned(buf[OFFSET_LC]);

    if (p1 == 0x04) {
      // Select the AID of the applet
      // do heavy verification, just for the fun of it ;)
      if (lc != (short) 0x0C) {
        ISOException.throwIt(SW_WRONG_LENGTH);
      }
      apdu.setIncomingAndReceive();
      if (Util.arrayCompare(buf, OFFSET_CDATA, myAID, (short) 0, lc) != 0) {
        ISOException.throwIt(SW_WRONG_DATA);
      }
      return;
    }

    short id = 0;
    switch (p1) {
      case (byte) 0x00:
        // Direct selection of MF, DF, or EF:
        if (lc != 0 && lc != 2) {
          ISOException.throwIt(SW_WRONG_LENGTH);
        }
        if (lc > 0) {
          apdu.setIncomingAndReceive();
          id = Util.makeShort(buf[OFFSET_CDATA], buf[(short) (OFFSET_CDATA + 1)]);
        } else {
          id = FileSystem.MASTER_FILE_ID;
        }
        if (!fileSystem.selectEntryAbsolute(id)) {
          ISOException.throwIt(SW_FILE_NOT_FOUND);
        }
        break;
      case (byte) 0x01:
      case (byte) 0x02:
        // Select the child under the current DF,
        // p1 0x01 DF identifier in data field
        // p1 0x02 EF identifier in data field
        if (lc != 2) {
          ISOException.throwIt(SW_WRONG_LENGTH);
        }
        apdu.setIncomingAndReceive();
        id = Util.makeShort(buf[OFFSET_CDATA], buf[(short) (OFFSET_CDATA + 1)]);
        if (!fileSystem.selectEntryUnderCurrent(id, p1 == (byte) 0x02)) {
          ISOException.throwIt(SW_FILE_NOT_FOUND);
        }
        break;
      case (byte) 0x03:
        // Select the parent of the current DF
        // no command data
        if (lc != 0) {
          ISOException.throwIt(SW_WRONG_LENGTH);
        }
        if (!fileSystem.selectEntryParent()) {
          ISOException.throwIt(SW_FILE_NOT_FOUND);
        }
        break;
      case (byte) 0x08:
      case (byte) 0x09:
        // Select by path
        // p1 0x08 from MF
        // p1 0x09 from current DF
        // data field: the path without the head
        if (lc == 0 || (short) (lc % 2) != 0) {
          ISOException.throwIt(SW_WRONG_LENGTH);
        }
        apdu.setIncomingAndReceive();
        if (!fileSystem.selectEntryByPath(buf, OFFSET_CDATA, lc, p1 == (byte) 0x08)) {
          ISOException.throwIt(SW_FILE_NOT_FOUND);
        }
        break;
      default:
        ISOException.throwIt(SW_INCORRECT_P1P2);
    }
  }