Package Com. NXP. Id. jcop. Training. filesystem; Import Javacard. Framework. Applet; Import Javacard. Framework. iso7816; Import Javacard. Framework. isoexception; Import Javacard. Framework. APDU; Import Javacard. Framework. jcsystem; Import Javacard. Framework. util; Public Class Filesystemapplet Extends Applet { Private Final Static Short File_version = ( Short ) 0x0100 ; // INS bytes Private Final Static Byte Ins_select_file = ( Byte ) 0xa4 ; Private Final Static Byte Ins_read_binary = ( Byte ) 0xb0 ; Private Final Static Byte Ins_update_binary = ( Byte ) 0xd6; // SW1 sw2 Public Static Final Short Sw_lc_inconsistent_with_p1p2 = ( Short ) 0x6a87 ; Public Static Final Short Sw_wrong_parameter_p1p2 = ( Short ) 0x6b00 ; // File Allocation Table Private Static Final Byte Fat_ef_1_id = 1 ; Private Static Final Byte Fat_ef_2_id = 2 ; // Fixed File Private Final Static Byte [] Ef_1_cvca_pubkey = {( Byte ) 0x04 ,( Byte ) 0x9d ,( Byte ) 0xdc ,( Byte ) 0x9e ,( Byte ) 0xbb ,( Byte ) 0xd2 ,( Byte ) 0xe0 ,( Byte ) 0x84 ,( Byte ) 0xbd,( Byte ) 0x69 ,( Byte ) 0xe4 ,( Byte ) 0xca ,( Byte ) 0x22 ,( Byte ) 0x2a ,( Byte ) 0x3c ,( Byte ) 0xcf ,( Byte ) 0x76 ,( Byte ) 0x03 ,( Byte ) 0x3e ,( Byte ) 0x47 ,(Byte ) 0x6b ,( Byte ) 0x04 ,( Byte ) 0xc7 ,( Byte ) 0xe5 ,( Byte ) 0x6e ,( Byte ) 0x40 ,( Byte ) 0x9e ,( Byte ) 0x2b ,( Byte ) 0xa1 ,( Byte ) 0xb9 ,( Byte ) 0xb7 ,(Byte ) 0x59 ,( Byte ) 0xb6 ,( Byte ) 0x79 ,( Byte ) 0xe2 ,( Byte ) 0x4c ,( Byte ) 0x7a ,( Byte ) 0xae ,( Byte ) 0x45 ,( Byte ) 0x26 ,( Byte ) 0xe8 ,( Byte ) 0xc1 ,( Byte ) 0x81 ,( Byte ) 0x65 ,( Byte ) 0x99 ,( Byte ) 0x7c ,( Byte ) 0x60 ,( Byte ) 0x29 ,( Byte ) 0x57 ,( Byte ) 0xf3 ,( Byte ) 0x8b ,( Byte ) 0xe8 ,( Byte ) 0x07 ,( Byte ) 0x03 ,( Byte ) 0xe5 ,( Byte ) 0xb7 ,( Byte ) 0x7a }; // Dynamic File Private Static Byte [] Ee_ef_2_data; // Filesystem Private Object [] ee_filesystem; // File selection flag Private Static Byte [] Ram_selectedfile; Public Filesystemapplet () {ee_ef_2_data = New Byte [( Short ) 0x3fff]; // Persistent 16 K Ee_filesystem = New Object [fat_ef_2_id + 1]; // Persistent filesystem reference Ee_filesystem [fat_ef_1_id] = (Object) ef_1_cvca_pubkey; ee_filesystem [fat_ef_2_id] = (Object) ee_ef_2_data; // Transient reference to the selected file Ram_selectedfile = jcsystem. maketransientbytearray (( Short ) 0 , Jcsystem. clear_on_deselect );} Public Static Void Install ( Byte [] Barray, Short Boffset, Byte Blength ){ // GP-compliant javacard applet Registration New Com. NXP. Id. jcop. Training. filesystem. filesystemapplet (). Register (barray ,( Short ) (Boffset + 1 ), Barray [boffset]);} Public Void Process (APDU ){ // Good practice: Return 9000 on select If (Selectingapplet () {util. setshort (APDU. getbuffer (),( Short ) 0 , File_version); APDU. setoutgoingandsend (( Short ) 0 ,( Short ) 2 ); Return ;} Byte [] Buf =APDU. getbuffer (); Short Ram_tempshort = 0; // Our fast stack variable // Retrieve P1P2 from APDU Buffer Short Ram_p1p2 = ( Short ) (Util. getshort (BUF, iso7816.offset _ P1 )); Switch (BUF [iso7816.offset _ ins]) { Case Ins_select_file: If (Ram_p1p2! = 0x0000) // Only select by file supported Isoexception. throwit (iso7816.sw _ incorrect_p1p2); ram_tempshort = APDU. setincomingandreceive (); If (Ram_tempshort! = 2) // File is 2 byte, located in the data field Isoexception. throwit (iso7816.sw _ wrong_length); ram_tempshort = Util. getshort (BUF, iso7816.offset _ CDATA ); Switch (Ram_tempshort ){ Case (Fat_ef_1_id): ram_selectedfile = ( Byte []) Ee_filesystem [fat_ef_1_id]; Break ; Case (Fat_ef_2_id): ram_selectedfile = ( Byte []) Ee_filesystem [fat_ef_2_id]; Break ; Default : Isoexception. throwit (iso7816.sw _ file_not_found );} // Switch Break ; Case Ins_read_binary: // Class 2 APDU (header and Le, not data field) If (Ram_selectedfile = Null ) // File must have been selected before (sfid not supported in this example) Isoexception. throwit (iso7816.sw _ file_not_found ); If (Ram_p1p2 &( Short ) 0x8000) = ( Short ) 0x8000) // Highest bit shall be 0 (sfid not supported in this example) Isoexception. throwit (iso7816.sw _ incorrect_p1p2 ); // Offset encoded in P1/P2, 15 lowest Bit Ram_tempshort =APDU. setoutgoing (); // Check if Le! = 0 <-- no response expected If (Ram_tempshort = 0 ) Isoexception. throwit (iso7816.sw _ wrong_length ); // Check offset If (Ram_p1p2> = Ram_selectedfile.length) isoexception. throwit (iso7816.sw _ incorrect_p1p2 ); // If Le = 256 --> output maximum remaining If (Ram_tempshort = 0x0100 ) Ram_tempshort = ( Short ) (Ram_selectedfile.length- Ram_p1p2 ); Else { // Check expected length If (( Short ) (Ram_p1p2 + ram_tempshort)> Ram_selectedfile.length) isoexception. throwit (iso7816.sw _ wrong_length);} util. arraycopynonatomic (ram_selectedfile, ram_p1p2, Buf ,( Short ) 0 , Ram_tempshort); APDU. setoutgoinglength (ram_tempshort); APDU. sendbytes (( Short ) 0 , Ram_tempshort ); Break ; Case Ins_update_binary: If (Ram_selectedfile = Null ) // File must have been selected before (sfid not supported in this example) Isoexception. throwit (iso7816.sw _ file_not_found ); // Update only allowed for dynamic File If (Ram_selectedfile = ( Byte []) Ee_filesystem [fat_ef_1_id]) isoexception. throwit (iso7816.sw _ file_invalid ); // Check offset and length Ram_tempshort = APDU. setincomingandreceive (); If (Ram_p1p2> = ram_selectedfile.length) |((( Short ) Ram_p1p2 + ram_tempshort)> = ram_selectedfile.length) | (Ram_tempshort = 0 ) Isoexception. throwit (iso7816.sw _ wrong_length); util. arraycopynonatomic (BUF, iso7816.offset _ CDATA, ram_selectedfile, ram_p1p2, ram_tempshort ); Break ; Default : // Good practice: if you don't know the instruction, say so: Isoexception. throwit (iso7816.sw _ ins_not_supported );}}} /* * Tasks * 0. create a second dymanic file EF_3: Max file size = 210 byte * 1. fill EF_3 with pseudo do random numbers * 2. read and Write into EF3 * Advanced * 3. create a cyclic file ef_4: Max file size = 50 byte * 4. write 2 time 120 bytes into ef_4 --> observe overwriting ** check out the scripts folder */
And the corresponding test script ..
# Select DF/Select |Fileapp # select ef_1/Send 00a40000020001 9000# Read Binary/Send 00b0000504*9000/send 00b0000000*9000/send 00b000007f 6700# Select ef_2/Send 00a40000020002 9000# UPDATE BINARY/Send limit 9000/send limit 6700# Read Binary/Send 00b000a020 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f9000