mirror of
https://github.com/status-im/status-keycard.git
synced 2025-02-05 10:24:09 +00:00
bring applet to protocol version 2.1
This commit is contained in:
parent
ca65db5c71
commit
eb73388e21
@ -8,7 +8,7 @@ import javacardx.crypto.Cipher;
|
||||
* The applet's main class. All incoming commands a processed by this class.
|
||||
*/
|
||||
public class KeycardApplet extends Applet {
|
||||
static final short APPLICATION_VERSION = (short) 0x0200;
|
||||
static final short APPLICATION_VERSION = (short) 0x0201;
|
||||
|
||||
static final byte INS_GET_STATUS = (byte) 0xF2;
|
||||
static final byte INS_SET_NDEF = (byte) 0xF3;
|
||||
@ -84,6 +84,14 @@ public class KeycardApplet extends Applet {
|
||||
static final byte TLV_APPLICATION_INFO_TEMPLATE = (byte) 0xA4;
|
||||
static final byte TLV_UID = (byte) 0x8F;
|
||||
static final byte TLV_KEY_UID = (byte) 0x8E;
|
||||
static final byte TLV_CAPABILITIES = (byte) 0x8D;
|
||||
|
||||
static final byte CAPABILITY_SECURE_CHANNEL = (byte) 0x01;
|
||||
static final byte CAPABILITY_KEY_MANAGEMENT = (byte) 0x02;
|
||||
static final byte CAPABILITY_CREDENTIALS_MANAGEMENT = (byte) 0x04;
|
||||
static final byte CAPABILITY_NDEF = (byte) 0x08;
|
||||
|
||||
static final byte APPLICATION_CAPABILITIES = (byte)(CAPABILITY_SECURE_CHANNEL | CAPABILITY_KEY_MANAGEMENT | CAPABILITY_CREDENTIALS_MANAGEMENT | CAPABILITY_NDEF);
|
||||
|
||||
static final byte[] EIP_1581_PREFIX = { (byte) 0x80, 0x00, 0x00, 0x2B, (byte) 0x80, 0x00, 0x00, 0x3C, (byte) 0x80, 0x00, 0x06, 0x2D};
|
||||
|
||||
@ -357,31 +365,50 @@ public class KeycardApplet extends Applet {
|
||||
|
||||
byte[] apduBuffer = apdu.getBuffer();
|
||||
|
||||
apduBuffer[0] = TLV_APPLICATION_INFO_TEMPLATE;
|
||||
apduBuffer[2] = TLV_UID;
|
||||
apduBuffer[3] = UID_LENGTH;
|
||||
Util.arrayCopyNonAtomic(uid, (short) 0, apduBuffer, (short) 4, UID_LENGTH);
|
||||
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[(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)] = secureChannel.getRemainingPairingSlots();
|
||||
apduBuffer[(short)(UID_LENGTH + keyLength + 13)] = TLV_KEY_UID;
|
||||
short off = 0;
|
||||
|
||||
apduBuffer[off++] = TLV_APPLICATION_INFO_TEMPLATE;
|
||||
|
||||
if (privateKey.isInitialized()) {
|
||||
apduBuffer[(short)(UID_LENGTH + keyLength + 14)] = KEY_UID_LENGTH;
|
||||
Util.arrayCopyNonAtomic(keyUID, (short) 0, apduBuffer, (short)(UID_LENGTH + keyLength + 15), KEY_UID_LENGTH);
|
||||
keyLength += KEY_UID_LENGTH;
|
||||
} else {
|
||||
apduBuffer[(short)(UID_LENGTH + keyLength + 14)] = 0;
|
||||
apduBuffer[off++] = (byte) 0x81;
|
||||
}
|
||||
|
||||
apduBuffer[1] = (byte)(keyLength + UID_LENGTH + 13);
|
||||
apdu.setOutgoingAndSend((short) 0, (short)(apduBuffer[1] + 2));
|
||||
short lenoff = off++;
|
||||
|
||||
apduBuffer[off++] = TLV_UID;
|
||||
apduBuffer[off++] = UID_LENGTH;
|
||||
Util.arrayCopyNonAtomic(uid, (short) 0, apduBuffer, off, UID_LENGTH);
|
||||
off += UID_LENGTH;
|
||||
|
||||
apduBuffer[off++] = TLV_PUB_KEY;
|
||||
short keyLength = secureChannel.copyPublicKey(apduBuffer, (short) (off + 1));
|
||||
apduBuffer[off++] = (byte) keyLength;
|
||||
off += keyLength;
|
||||
|
||||
apduBuffer[off++] = TLV_INT;
|
||||
apduBuffer[off++] = 2;
|
||||
Util.setShort(apduBuffer, off, APPLICATION_VERSION);
|
||||
off += 2;
|
||||
|
||||
apduBuffer[off++] = TLV_INT;
|
||||
apduBuffer[off++] = 1;
|
||||
apduBuffer[off++] = secureChannel.getRemainingPairingSlots();
|
||||
apduBuffer[off++] = TLV_KEY_UID;
|
||||
|
||||
if (privateKey.isInitialized()) {
|
||||
apduBuffer[off++] = KEY_UID_LENGTH;
|
||||
Util.arrayCopyNonAtomic(keyUID, (short) 0, apduBuffer, off, KEY_UID_LENGTH);
|
||||
off += KEY_UID_LENGTH;
|
||||
} else {
|
||||
apduBuffer[off++] = 0;
|
||||
}
|
||||
|
||||
apduBuffer[off++] = TLV_CAPABILITIES;
|
||||
apduBuffer[off++] = 1;
|
||||
apduBuffer[off++] = APPLICATION_CAPABILITIES;
|
||||
|
||||
apduBuffer[lenoff] = (byte)(off - lenoff - 1);
|
||||
apdu.setOutgoingAndSend((short) 0, off);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,7 @@ package im.status.keycard;
|
||||
import com.licel.jcardsim.smartcardio.CardSimulator;
|
||||
import com.licel.jcardsim.smartcardio.CardTerminalSimulator;
|
||||
import com.licel.jcardsim.utils.AIDUtil;
|
||||
import im.status.keycard.applet.ApplicationInfo;
|
||||
import im.status.keycard.applet.Identifiers;
|
||||
import im.status.keycard.applet.KeycardCommandSet;
|
||||
import im.status.keycard.desktop.PCSCCardChannel;
|
||||
@ -168,10 +169,10 @@ public class KeycardTest {
|
||||
|
||||
// Verify that the keys are changed correctly. Since we do not know the internal counter we just iterate until that
|
||||
// happens for a maximum of SC_COUNTER_MAX times
|
||||
byte[] initialKey = extractPublicKeyFromSelect(cmdSet.select().getData());
|
||||
byte[] initialKey = new ApplicationInfo(cmdSet.select().getData()).getSecureChannelPubKey();
|
||||
|
||||
for (int i = 0; i < SecureChannel.SC_COUNTER_MAX; i++) {
|
||||
byte[] otherKey = extractPublicKeyFromSelect(cmdSet.select().getData());
|
||||
byte[] otherKey = new ApplicationInfo(cmdSet.select().getData()).getSecureChannelPubKey();
|
||||
|
||||
if (!Arrays.equals(initialKey, otherKey)) {
|
||||
secureChannel.generateSecret(otherKey);
|
||||
@ -697,9 +698,8 @@ public class KeycardTest {
|
||||
|
||||
response = cmdSet.select();
|
||||
assertEquals(0x9000, response.getSw());
|
||||
byte[] data = response.getData();
|
||||
assertEquals(32, data[30 + data[21]]);
|
||||
verifyKeyUID(Arrays.copyOfRange(data, (31 + data[21]), (63 + data[21])), (ECPublicKey) keyPair.getPublic());
|
||||
ApplicationInfo info = new ApplicationInfo(response.getData());
|
||||
verifyKeyUID(info.getKeyUID(), (ECPublicKey) keyPair.getPublic());
|
||||
|
||||
cmdSet.autoOpenSecureChannel();
|
||||
response = cmdSet.verifyPIN("000000");
|
||||
@ -715,8 +715,8 @@ public class KeycardTest {
|
||||
|
||||
response = cmdSet.select();
|
||||
assertEquals(0x9000, response.getSw());
|
||||
data = response.getData();
|
||||
assertEquals(0, data[30 + data[21]]);
|
||||
info = new ApplicationInfo(response.getData());
|
||||
assertEquals(0, info.getKeyUID().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1229,14 +1229,6 @@ public class KeycardTest {
|
||||
return Arrays.copyOfRange(sig, 5, 5 + sig[4]);
|
||||
}
|
||||
|
||||
private byte[] extractPublicKeyFromSelect(byte[] select) {
|
||||
assertEquals(KeycardApplet.TLV_APPLICATION_INFO_TEMPLATE, select[0]);
|
||||
assertEquals(KeycardApplet.TLV_UID, select[2]);
|
||||
assertEquals(KeycardApplet.TLV_PUB_KEY, select[20]);
|
||||
|
||||
return Arrays.copyOfRange(select, 22, 22 + select[21]);
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
if (USE_SIMULATOR) {
|
||||
simulator.reset();
|
||||
|
Loading…
x
Reference in New Issue
Block a user