/* (non-Javadoc) * @see org.opensc.pkcs15.token.Token#deleteEF(int) */ @Override public void deleteEF(int path) throws IOException { // DELETE FILE, P1=0x00, P2=0x00, ID -> read current EF from position 0. CommandAPDU cmd = new CommandAPDU(0x00, 0xE4, 0x00, 0x00, PathHelper.idToPath(path), DEFAULT_LE); try { ResponseAPDU resp = this.channel.transmit(cmd); if (resp.getSW() != PKCS15Exception.ERROR_OK) throw new PKCS15Exception( "DELETE FILE for EF [" + PathHelper.formatPathAppend(this.currentFile.getPath(), path) + "] returned error", resp.getSW()); } catch (CardException e) { throw new PKCS15Exception( "Error sending DELETE FILE for EF [" + PathHelper.formatPathAppend(this.currentFile.getPath(), path) + "]", e); } }
/* (non-Javadoc) * @see org.opensc.pkcs15.token.Token#selectDF(int) */ @Override public DF selectDF(int path) throws IOException { if (this.currentFile == null) throw new IOException("No current DF selected."); // SELECT FILE, P1=0x01, P2=0x00, no data -> select DF CommandAPDU cmd = new CommandAPDU(0x00, 0xA4, 0x01, 0x00, PathHelper.idToPath(path), DEFAULT_LE); return this.selectDFInternal(cmd, new TokenPath(this.currentFile.getPath(), path)); }
/* (non-Javadoc) * @see org.opensc.pkcs15.token.Token#selectMF() */ @Override public MF selectMF() throws IOException { // SELECT FILE, P1=0x00, P2=0x00, no data -> select MF CommandAPDU cmd = new CommandAPDU(0x00, 0xA4, 0x00, 0x00, DEFAULT_LE); try { ResponseAPDU resp = this.channel.transmit(cmd); DataInputStream dis = getSelectFileData(resp); long bodySize = 0; int acLifeCycle = TokenFileAcl.AC_ALWAYS; int acUpdate = TokenFileAcl.AC_ALWAYS; int acAppend = TokenFileAcl.AC_ALWAYS; int acDeactivate = TokenFileAcl.AC_ALWAYS; int acActivate = TokenFileAcl.AC_ALWAYS; int acDelete = TokenFileAcl.AC_ALWAYS; int acAdmin = TokenFileAcl.AC_ALWAYS; int acCreate = TokenFileAcl.AC_ALWAYS; int acExecute = TokenFileAcl.AC_ALWAYS; int acAllocate = TokenFileAcl.AC_ALWAYS; int tag; while ((tag = dis.read()) >= 0) { int n = dis.read(); if (n < 0) break; switch (tag) { case 0x81: if (n != 2) throw new IOException("Invalid length [" + n + "] of FCI tag 0x81."); bodySize = dis.readUnsignedShort(); break; case 0x83: if (n != 2) throw new IOException("Invalid length [" + n + "] of FCI tag 0x83."); int tpath = dis.readUnsignedShort(); if (tpath != PathHelper.MF_ID) throw new IOException( "File ID [" + PathHelper.formatID(tpath) + "] reported by SELECT FILE differs from requested ID [" + PathHelper.formatID(PathHelper.MF_ID) + "]."); break; case 0x86: if (n >= 1) acLifeCycle = dis.read(); if (n >= 2) acUpdate = dis.read(); if (n >= 3) acAppend = dis.read(); if (n >= 4) acDeactivate = dis.read(); if (n >= 5) acActivate = dis.read(); if (n >= 6) acDelete = dis.read(); if (n >= 7) acAdmin = dis.read(); if (n >= 8) acCreate = dis.read(); if (n >= 9) acExecute = dis.read(); if (n >= 10) acAllocate = dis.read(); if (n != 10) log.warn("Invalid length [" + n + "] of FCI tag 0x86 for MF."); if (n > 10) dis.skipBytes(n - 10); break; default: byte[] tmp = new byte[n]; dis.readFully(tmp); log.warn( "skipping FCI tag [0x" + Integer.toHexString(tag) + "], data [" + Util.asHex(tmp) + "]."); } } MF mf = new MF( PathHelper.MF_PATH, bodySize, acLifeCycle, acUpdate, acAppend, acDeactivate, acActivate, acDelete, acAdmin, acCreate, acExecute, acAllocate); this.currentFile = mf; return mf; } catch (CardException e) { throw new PKCS15Exception("Error sending select MF", e); } }
/* (non-Javadoc) * @see org.opensc.pkcs15.token.Token#selectEF(int) */ @Override public EF selectEF(int path) throws IOException { if (this.currentFile == null) throw new IOException("No current DF selected."); // SELECT FILE, P1=0x02, P2=0x00, no data -> select EF CommandAPDU cmd = new CommandAPDU(0x00, 0xA4, 0x02, 0x00, PathHelper.idToPath(path), DEFAULT_LE); try { ResponseAPDU resp = this.channel.transmit(cmd); DataInputStream dis = getSelectFileData(resp); long fileSize = 0; int acRead = TokenFileAcl.AC_ALWAYS; int acUpdate = TokenFileAcl.AC_ALWAYS; int acAppend = TokenFileAcl.AC_ALWAYS; int acDeactivate = TokenFileAcl.AC_ALWAYS; int acActivate = TokenFileAcl.AC_ALWAYS; int acDelete = TokenFileAcl.AC_ALWAYS; int acAdmin = TokenFileAcl.AC_ALWAYS; int acIncrease = TokenFileAcl.AC_ALWAYS; int acDecrease = TokenFileAcl.AC_ALWAYS; int tag; while ((tag = dis.read()) >= 0) { int n = dis.read(); if (n < 0) break; switch (tag) { case 0x80: if (n != 2) throw new IOException("Invalid length [" + n + "] of FCI tag 0x80."); fileSize = dis.readUnsignedShort(); break; case 0x83: if (n != 2) throw new IOException("Invalid length [" + n + "] of FCI tag 0x83."); int tpath = dis.readUnsignedShort(); if (tpath != path) throw new IOException( "File ID [" + PathHelper.formatID(tpath) + "] reported by SELECT FILE differs from requested ID [" + PathHelper.formatID(path) + "]."); break; case 0x86: if (n >= 1) acRead = dis.read(); if (n >= 2) acUpdate = dis.read(); if (n >= 3) acAppend = dis.read(); if (n >= 4) acDeactivate = dis.read(); if (n >= 5) acActivate = dis.read(); if (n >= 6) acDelete = dis.read(); if (n >= 7) acAdmin = dis.read(); if (n >= 8) acIncrease = dis.read(); if (n >= 9) acDecrease = dis.read(); if (n != 9) log.warn("Invalid length [" + n + "] of FCI tag 0x86 for EF."); if (n > 9) dis.skipBytes(n - 9); break; default: byte[] tmp = new byte[n]; dis.readFully(tmp); log.warn( "skipping FCI tag [0x" + Integer.toHexString(tag) + "], data [" + Util.asHex(tmp) + "]."); } } EF ef = new EF( new TokenPath(this.currentFile.getPath(), path), fileSize, acRead, acUpdate, acAppend, acDeactivate, acActivate, acDelete, acAdmin, acIncrease, acDecrease); this.currentFile = ef; return ef; } catch (CardException e) { throw new PKCS15Exception("Error sending select MF", e); } }
private DF selectDFInternal(CommandAPDU cmd, TokenPath targetPath) throws IOException { try { ResponseAPDU resp = this.channel.transmit(cmd); DataInputStream dis = getSelectFileData(resp); long bodySize = 0; int acLifeCycle = TokenFileAcl.AC_ALWAYS; int acUpdate = TokenFileAcl.AC_ALWAYS; int acAppend = TokenFileAcl.AC_ALWAYS; int acDeactivate = TokenFileAcl.AC_ALWAYS; int acActivate = TokenFileAcl.AC_ALWAYS; int acDelete = TokenFileAcl.AC_ALWAYS; int acAdmin = TokenFileAcl.AC_ALWAYS; int acCreate = TokenFileAcl.AC_ALWAYS; int tag; while ((tag = dis.read()) >= 0) { int n = dis.read(); if (n < 0) break; switch (tag) { case 0x81: if (n != 2) throw new IOException("Invalid length [" + n + "] of FCI tag 0x81."); bodySize = dis.readUnsignedShort(); break; case 0x83: if (n != 2) throw new IOException("Invalid length [" + n + "] of FCI tag 0x83."); int tpath = dis.readUnsignedShort(); if (tpath != targetPath.getTailID()) throw new IOException( "File ID [" + PathHelper.formatID(tpath) + "] reported by SELECT FILE differs from requested ID [" + PathHelper.formatID(targetPath.getTailID()) + "]."); break; case 0x86: if (n >= 1) acLifeCycle = dis.read(); if (n >= 2) acUpdate = dis.read(); if (n >= 3) acAppend = dis.read(); if (n >= 4) acDeactivate = dis.read(); if (n >= 5) acActivate = dis.read(); if (n >= 6) acDelete = dis.read(); if (n >= 7) acAdmin = dis.read(); if (n >= 8) acCreate = dis.read(); if (n != 8) log.warn("Invalid length [" + n + "] of FCI tag 0x86 for DF."); if (n > 8) dis.skipBytes(n - 8); break; default: byte[] tmp = new byte[n]; dis.readFully(tmp); log.warn( "skipping FCI tag [0x" + Integer.toHexString(tag) + "], data [" + Util.asHex(tmp) + "]."); } } DF df = new DF( targetPath, bodySize, acLifeCycle, acUpdate, acAppend, acDeactivate, acActivate, acDelete, acAdmin, acCreate); this.currentFile = df; return df; } catch (CardException e) { throw new PKCS15Exception("Error sending select MF", e); } }
/* (non-Javadoc) * @see org.opensc.pkcs15.token.Token#createEF(int, org.opensc.pkcs15.token.EFAcl) */ @Override public EF createEF(int path, long size, EFAcl acl) throws IOException { if (size < 0 || size > 65535L) throw new PKCS15Exception( "Illegal size [" + size + "] for EF [" + PathHelper.formatPathAppend(this.currentFile.getPath(), path) + "].", PKCS15Exception.ERROR_INVALID_PARAMETER); ByteArrayOutputStream bos = new ByteArrayOutputStream(256); DataOutputStream dos = new DataOutputStream(bos); dos.write(0x62); // length of subsequent FCP data field, to be filled at end. dos.write(0x00); // *** fill in FCP data // Only EF: Net size in bytes dos.write(0x80); dos.write(0x02); dos.writeShort((int) size); // File descriptor: 01h BINARY dos.write(0x82); dos.write(0x01); dos.write(0x01); // File ID dos.write(0x83); dos.write(0x02); dos.writeShort(path); // Default file status. dos.write(0x85); dos.write(0x01); dos.write(0x00); // ACL definitions dos.write(0x86); dos.write(0x09); dos.write(acl.getAcRead()); dos.write(acl.getAcUpdate()); dos.write(acl.getAcAppend()); dos.write(acl.getAcDeactivate()); dos.write(acl.getAcActivate()); dos.write(acl.getAcDelete()); dos.write(acl.getAcAdmin()); dos.write(acl.getAcIncrease()); dos.write(acl.getAcDecrease()); // *** get command data. dos.flush(); byte[] data = bos.toByteArray(); // fill in length of subsequent FCP data field, to be filled at end. data[1] = (byte) (data.length - 2); // CREATE FILE, P1=0x00, P2=0x00, ID -> read current EF from position 0. CommandAPDU cmd = new CommandAPDU(0x00, 0xE0, 0x00, 0x00, data, DEFAULT_LE); try { ResponseAPDU resp = this.channel.transmit(cmd); if (resp.getSW() != PKCS15Exception.ERROR_OK) throw new PKCS15Exception( "CREATE FILE for EF [" + PathHelper.formatPathAppend(this.currentFile.getPath(), path) + "] returned error", resp.getSW()); } catch (CardException e) { throw new PKCS15Exception( "Error sending CREATE FILE for EF [" + PathHelper.formatPathAppend(this.currentFile.getPath(), path) + "]", e); } return new EF(new TokenPath(this.currentFile.getPath(), path), size, acl); }