/** * Reads data from the current selected file (INS 0xB0) * * @param offset Offset at which to start reading * @param nbBytes Number of bytes to read * @return Data retreived from the file */ public byte[] readBinary(int offset, int nbBytes) throws SecureElementException { if (mFileSize == 0) return null; if (nbBytes == -1) nbBytes = mFileSize; if (mFileType != EF) throw new SecureElementException("Incorrect file type"); if (mFileStructure != TRANSPARENT) throw new SecureElementException("Incorrect file structure"); int length, pos = 0; byte[] result = new byte[nbBytes]; byte[] cmd = {0x00, (byte) 0xB0, 0x00, 0x00, 0x00}; while (nbBytes != 0) { if (nbBytes < BUFFER_LEN) length = nbBytes; else length = BUFFER_LEN; // Set to max buffer size Log.d(TAG, "ReadBinary [" + offset + ".." + length + "b]"); cmd[2] = (byte) (offset >> 8); cmd[3] = (byte) offset; cmd[4] = (byte) length; System.arraycopy(mSEHandle.exchangeAPDU(this, cmd), 0, result, pos, length); nbBytes -= length; offset += length; pos += length; } return result; }
/** * Selects a file (INS 0xA4) * * @param path Path of the file * @return Command status code [sw1 sw2] */ public int selectFile(byte[] path) throws SecureElementException { if ((path == null) || (path.length == 0) || ((path.length % 2) != 0)) throw new SecureElementException("Incorrect path"); int index; int length = path.length; if ((mSEHandle.getSeInterface() == SecureElement.SIM_IO) && (length > 2)) { index = length - 2; // Only FileID is usefull mFilePath = Util.bytesToString(path, 0, index, ""); } else { index = 0; mFilePath = ""; } byte[] data = null; byte[] cmd = new byte[] {0x00, (byte) 0xA4, 0x00, 0x04, 0x02, 0x00, 0x00}; mFileType = UNKNOWN; mFileStructure = UNKNOWN; mFileSize = 0; mFileRecordSize = 0; mFileNbRecords = 0; // iterate through path for (int sw1; index < length; index += 2) { mFileID = ((path[index] & 0xFF) << 8) | (path[index + 1] & 0xFF); cmd[5] = (byte) (mFileID >> 8); cmd[6] = (byte) mFileID; data = mSEHandle.exchangeAPDU(this, cmd); // Check ADPU status sw1 = data[data.length - 2] & 0xFF; if ((sw1 != 0x62) && (sw1 != 0x63) && (sw1 != 0x90) && (sw1 != 0x91)) { return (sw1 << 8) | (data[data.length - 1] & 0xFF); } } // Analyse file properties decodeFileProperties(data); if (mFileNbRecords == 0) Log.d(TAG, "SelectFile [" + mFileSize + "b]"); else Log.d(TAG, "SelectFile [" + mFileNbRecords + "*" + mFileRecordSize + "b]"); return APDU_SUCCESS; }
/** * Reads a record from the current selected file (INS 0xB2) * * @param record Record ID [0..n] * @return Data from requested record */ public byte[] readRecord(short record) throws SecureElementException { // Check the type of current selected file if (mFileType != EF) throw new SecureElementException("Incorrect file type"); if (mFileStructure != LINEAR_FIXED) throw new SecureElementException("Incorrect file structure"); // Check if requested record is valid if ((record < 0) || (record > mFileNbRecords)) throw new SecureElementException("Incorrect record number"); Log.d(TAG, "ReadRecord [" + record + "/" + mFileRecordSize + "b]"); byte[] cmd = {0x00, (byte) 0xB2, (byte) record, 0x04, (byte) mFileRecordSize}; return Arrays.copyOf(mSEHandle.exchangeAPDU(this, cmd), mFileRecordSize); }