/**
  * Searches for an index to the file specified by the id in the file structure starting from
  * position start.
  *
  * @param fileStructureArray the array with the file structure
  * @param shift the shift in the input array (e.g. when the array is the APDU with the header
  *     bytes)
  * @param start starting position to search
  * @param lastOffset the last valid offset in the input array
  * @param id the id of the file that is searched
  * @return the index of the file, if found
  * @throws ArrayIndexOutOfBoundsException when start and lastOffset point outside of the input
  *     array
  * @throws FileNotFoundException when file not found
  */
 short searchId(byte[] fileStructureArray, short shift, short start, short lastOffset, short id)
     throws ArrayIndexOutOfBoundsException, FileNotFoundException {
   if (start < 0 || start > (short) (lastOffset - 5)) {
     // This sould produce ArrayIndexOutOfBoundsException
     fileStructureArray[fileStructureArray.length] = (byte) 0xFF;
   }
   short fid = Util.getShort(fileStructureArray, (short) (start + 1));
   if (fid == id) {
     return start;
   }
   if (fileStructureArray[start] != DIR) {
     throw fnfe;
   } else {
     short childNum = fileStructureArray[(short) (start + 4)];
     if (start > (short) ((short) (lastOffset - 5) - childNum)) {
       fileStructureArray[fileStructureArray.length] = (byte) 0xFF;
     }
     for (short i = 0; i < childNum; i++) {
       try {
         return searchId(
             fileStructureArray,
             shift,
             (short) (fileStructureArray[(short) (start + (short) (5 + i))] + shift),
             lastOffset,
             id);
       } catch (FileNotFoundException e) {
       }
     }
   }
   throw fnfe;
 }
Exemple #2
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;
  }
 private void processCreateFile(APDU apdu) {
   if (state != STATE_INITIAL) {
     ISOException.throwIt(SW_INS_NOT_SUPPORTED);
   }
   byte[] buf = apdu.getBuffer();
   short lc = unsigned(buf[OFFSET_LC]);
   apdu.setIncomingAndReceive();
   if (lc != 5) {
     ISOException.throwIt(SW_WRONG_LENGTH);
   }
   short offset = OFFSET_CDATA;
   short id = Util.getShort(buf, offset);
   offset += 2;
   short len = Util.getShort(buf, offset);
   offset += 2;
   byte perm = buf[offset];
   if (!fileSystem.createFile(id, len, perm)) {
     ISOException.throwIt(SW_WRONG_DATA);
   }
 }
Exemple #4
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;
  }
Exemple #5
0
 /**
  * \brief Decode the length field of a TLV-entry.
  *
  * <p>The length field itself can be 1, 2 or 3 bytes long: - If the length is between 0 and 127,
  * it is 1 byte long. - If the length is between 128 and 255, it is 2 bytes long. The first byte
  * is 0x81 to indicate this. - If the length is between 256 and 65535, it is 3 bytes long. The
  * first byte is 0x82, the following 2 contain the actual length. Note: Only lengths up to 0x7FFF
  * (32767) are supported here, because a short in Java is signed.
  *
  * <p>\param buf The buffer containing the length field.
  *
  * <p>\param offset The offset at where the length field starts.
  *
  * <p>\param length The length of the buffer (buf). This is to prevent that the index gets out of
  * bounds.
  *
  * <p>\return The (positive) length encoded by the length field, or in case of an error, -1.
  *
  * <p>\throw InvalidArgumentsException If offset is too big for a signed Java short If the first
  * byte of the length field is invalid
  */
 public static short decodeLengthField(byte[] buf, short offset) throws InvalidArgumentsException {
   if (buf[offset] == (byte) 0x82) { // 256..65535
     // Check for short overflow
     // (In Java, a short is signed: positive values are 0000..7FFF)
     if (buf[(short) (offset + 1)] < 0) { // 80..FF
       throw InvalidArgumentsException.getInstance();
     }
     return Util.getShort(buf, (short) (offset + 1));
   } else if (buf[offset] == (byte) 0x81) {
     return (short) (0x00FF & buf[(short) (offset + 1)]);
   } else if (buf[offset] > 0) { // 00..7F
     return (short) (0x007F & buf[offset]);
   } else {
     throw InvalidArgumentsException.getInstance();
   }
 }
    private short findEntryRelative(short start, short id) throws FileNotFoundException {
      try {
        if (fileStructure[start] != DIR) {
          throw fnfe;
        }
        short childNum = fileStructure[(short) (start + 4)];

        for (short i = 0; i < childNum; i++) {
          short index = fileStructure[(short) (start + (short) (5 + i))];
          short fid = Util.getShort(fileStructure, (short) (index + 1));
          if (fid == id) {
            return index;
          }
        }
      } catch (ArrayIndexOutOfBoundsException aioobe) {

      }
      throw fnfe;
    }
 private short getFileIndex(short fid) throws ISOException {
   short result = -1;
   switch (fid) {
     case EF_DG1_FID:
       result = EF_DG1_INDEX;
       break;
     case EF_DG2_FID:
       result = EF_DG2_INDEX;
       break;
     case EF_DG3_FID:
       result = EF_DG3_INDEX;
       break;
     case EF_DG4_FID:
       result = EF_DG4_INDEX;
       break;
     case EF_DG5_FID:
       result = EF_DG5_INDEX;
       break;
     case EF_DG6_FID:
       result = EF_DG6_INDEX;
       break;
     case EF_DG7_FID:
       result = EF_DG7_INDEX;
       break;
     case EF_DG8_FID:
       result = EF_DG8_INDEX;
       break;
     case EF_DG9_FID:
       result = EF_DG9_INDEX;
       break;
     case EF_DG10_FID:
       result = EF_DG10_INDEX;
       break;
     case EF_DG11_FID:
       result = EF_DG11_INDEX;
       break;
     case EF_DG12_FID:
       result = EF_DG12_INDEX;
       break;
     case EF_DG13_FID:
       result = EF_DG13_INDEX;
       break;
     case EF_DG14_FID:
       result = EF_DG14_INDEX;
       break;
     case EF_DG15_FID:
       result = EF_DG15_INDEX;
       break;
     case EF_DG16_FID:
       result = EF_DG16_INDEX;
       break;
     case EF_SOD_FID:
       result = EF_SOD_INDEX;
       break;
     case EF_COM_FID:
       result = EF_COM_INDEX;
       break;
     default:
       result = -1;
       break;
   }
   if (result != -1 && SmartIDApplet.isLocked() && SmartIDApplet.hasMutualAuthenticationKeys()) {
     // We are in the personalized state and BAC is active,
     // we need to control the access
     // a. check that the current authorization level is sufficient to
     // access
     // the given file
     // b. if we are passed the EAC protocol we also need to check
     // whether the current certificate authorization allows us to read the file.
     byte perm = filePerms[result];
     if ((byte) (perm & SmartIDApplet.volatileState[0]) != perm) {
       ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
     }
     if (result <= EF_DG16_INDEX
         && SmartIDApplet.hasTerminalAuthenticated()
         && perm == SmartIDApplet.TERMINAL_AUTHENTICATED) {
       short m = (short) (0x1 << result);
       if ((Util.getShort(currentAuthorization, (short) 1) & m) != m) {
         ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
       }
     }
   }
   return result;
 }