diff --git a/APPLICATION.MD b/APPLICATION.MD index 2792c18..9696420 100644 --- a/APPLICATION.MD +++ b/APPLICATION.MD @@ -52,13 +52,17 @@ SW 0x6985 is returned. All tagged data structures are encoded in the [BER-TLV fo Response Data format: - Tag 0xA4 = Application Info Template - - Tag 0x4F = Instance UID (16 bytes) + - Tag 0x8F = Instance UID (16 bytes) - Tag 0x80 = ECC public Key + - Tag 0x02 = Application Version (2 bytes) + - Tag 0x02 = PUK retry count (1 byte) The SELECT command is documented in the ISO 7816-4 specifications and is used to select the application on the card, making it the active one. The data field is the AID of the application. The response is the Application Info template which contains the instance UID (which can be used by the client to keep track of multiple cards) and the public key -which must be used by the client to establish the Secure Channel. +which must be used by the client to establish the Secure Channel. Additionally it contains the version number of the +application, formatted on two bytes. The first byte is the major version and the second is the minor version +(e.g: version 1.1 is formatted as 0x0101). The PUK retry count is also included in the response. ### OPEN SECURE CHANNEL diff --git a/build.gradle b/build.gradle index 4028118..fd7a82f 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ javacard { aid = '0x53:0x74:0x61:0x74:0x75:0x73:0x57:0x61:0x6c:0x6c:0x65:0x74:0x41:0x70:0x70' className = 'WalletApplet' } - version = '1.0' + version = '1.1' } } diff --git a/src/main/java/im/status/wallet/WalletApplet.java b/src/main/java/im/status/wallet/WalletApplet.java index a7059c6..028706e 100644 --- a/src/main/java/im/status/wallet/WalletApplet.java +++ b/src/main/java/im/status/wallet/WalletApplet.java @@ -7,6 +7,8 @@ import javacard.security.*; * The applet's main class. All incoming commands a processed by this class. */ public class WalletApplet extends Applet { + static final short APPLICATION_VERSION = (short) 0x0101; + static final byte INS_GET_STATUS = (byte) 0xF2; static final byte INS_VERIFY_PIN = (byte) 0x20; static final byte INS_CHANGE_PIN = (byte) 0x21; @@ -305,7 +307,13 @@ public class WalletApplet extends Applet { apduBuffer[(short)(UID_LENGTH + 4)] = TLV_PUB_KEY; short keyLength = secureChannel.copyPublicKey(apduBuffer, (short) (UID_LENGTH + 6)); apduBuffer[(short)(UID_LENGTH + 5)] = (byte) keyLength; - apduBuffer[1] = (byte)(keyLength + UID_LENGTH + 4); + apduBuffer[(short)(UID_LENGTH + keyLength + 6)] = TLV_INT; + apduBuffer[(short)(UID_LENGTH + keyLength + 7)] = 2; + Util.setShort(apduBuffer, (short)(UID_LENGTH + keyLength + 8), APPLICATION_VERSION); + apduBuffer[(short)(UID_LENGTH + keyLength + 10)] = TLV_INT; + apduBuffer[(short)(UID_LENGTH + keyLength + 11)] = 1; + apduBuffer[(short)(UID_LENGTH + keyLength + 12)] = puk.getTriesRemaining(); + apduBuffer[1] = (byte)(keyLength + UID_LENGTH + 11); apdu.setOutgoingAndSend((short) 0, (short)(apduBuffer[1] + 2)); } diff --git a/src/test/java/im/status/wallet/WalletAppletTest.java b/src/test/java/im/status/wallet/WalletAppletTest.java index 90d7ab9..a9e4c53 100644 --- a/src/test/java/im/status/wallet/WalletAppletTest.java +++ b/src/test/java/im/status/wallet/WalletAppletTest.java @@ -112,6 +112,10 @@ public class WalletAppletTest { assertEquals(WalletApplet.TLV_APPLICATION_INFO_TEMPLATE, data[0]); assertEquals(WalletApplet.TLV_UID, data[2]); assertEquals(WalletApplet.TLV_PUB_KEY, data[20]); + assertEquals(WalletApplet.TLV_INT, data[22 + data[21]]); + assertEquals(WalletApplet.APPLICATION_VERSION >> 8, data[24 + data[21]]); + assertEquals(WalletApplet.APPLICATION_VERSION & 0xFF, data[25 + data[21]]); + assertEquals(WalletApplet.TLV_INT, data[26 + data[21]]); } @Test @@ -1054,7 +1058,7 @@ public class WalletAppletTest { assertEquals(WalletApplet.TLV_UID, select[2]); assertEquals(WalletApplet.TLV_PUB_KEY, select[20]); - return Arrays.copyOfRange(select, 22, select.length); + return Arrays.copyOfRange(select, 22, 22 + select[21]); } private void reset() {