add application version and PUK retry count to select
This commit is contained in:
parent
ae6490c132
commit
d98eafd6b6
|
@ -52,13 +52,17 @@ SW 0x6985 is returned. All tagged data structures are encoded in the [BER-TLV fo
|
||||||
|
|
||||||
Response Data format:
|
Response Data format:
|
||||||
- Tag 0xA4 = Application Info Template
|
- Tag 0xA4 = Application Info Template
|
||||||
- Tag 0x4F = Instance UID (16 bytes)
|
- Tag 0x8F = Instance UID (16 bytes)
|
||||||
- Tag 0x80 = ECC public Key
|
- 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,
|
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
|
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 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
|
### OPEN SECURE CHANNEL
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ javacard {
|
||||||
aid = '0x53:0x74:0x61:0x74:0x75:0x73:0x57:0x61:0x6c:0x6c:0x65:0x74:0x41:0x70:0x70'
|
aid = '0x53:0x74:0x61:0x74:0x75:0x73:0x57:0x61:0x6c:0x6c:0x65:0x74:0x41:0x70:0x70'
|
||||||
className = 'WalletApplet'
|
className = 'WalletApplet'
|
||||||
}
|
}
|
||||||
version = '1.0'
|
version = '1.1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import javacard.security.*;
|
||||||
* The applet's main class. All incoming commands a processed by this class.
|
* The applet's main class. All incoming commands a processed by this class.
|
||||||
*/
|
*/
|
||||||
public class WalletApplet extends Applet {
|
public class WalletApplet extends Applet {
|
||||||
|
static final short APPLICATION_VERSION = (short) 0x0101;
|
||||||
|
|
||||||
static final byte INS_GET_STATUS = (byte) 0xF2;
|
static final byte INS_GET_STATUS = (byte) 0xF2;
|
||||||
static final byte INS_VERIFY_PIN = (byte) 0x20;
|
static final byte INS_VERIFY_PIN = (byte) 0x20;
|
||||||
static final byte INS_CHANGE_PIN = (byte) 0x21;
|
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;
|
apduBuffer[(short)(UID_LENGTH + 4)] = TLV_PUB_KEY;
|
||||||
short keyLength = secureChannel.copyPublicKey(apduBuffer, (short) (UID_LENGTH + 6));
|
short keyLength = secureChannel.copyPublicKey(apduBuffer, (short) (UID_LENGTH + 6));
|
||||||
apduBuffer[(short)(UID_LENGTH + 5)] = (byte) keyLength;
|
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));
|
apdu.setOutgoingAndSend((short) 0, (short)(apduBuffer[1] + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,10 @@ public class WalletAppletTest {
|
||||||
assertEquals(WalletApplet.TLV_APPLICATION_INFO_TEMPLATE, data[0]);
|
assertEquals(WalletApplet.TLV_APPLICATION_INFO_TEMPLATE, data[0]);
|
||||||
assertEquals(WalletApplet.TLV_UID, data[2]);
|
assertEquals(WalletApplet.TLV_UID, data[2]);
|
||||||
assertEquals(WalletApplet.TLV_PUB_KEY, data[20]);
|
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
|
@Test
|
||||||
|
@ -1054,7 +1058,7 @@ public class WalletAppletTest {
|
||||||
assertEquals(WalletApplet.TLV_UID, select[2]);
|
assertEquals(WalletApplet.TLV_UID, select[2]);
|
||||||
assertEquals(WalletApplet.TLV_PUB_KEY, select[20]);
|
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() {
|
private void reset() {
|
||||||
|
|
Loading…
Reference in New Issue