add instance UID
This commit is contained in:
parent
a61369d1bc
commit
09fe778d85
|
@ -48,11 +48,17 @@ SW 0x6985 is returned. All tagged data structures are encoded in the [BER-TLV fo
|
||||||
* P1 = 0x04
|
* P1 = 0x04
|
||||||
* P2 = 0x00
|
* P2 = 0x00
|
||||||
* Data = 53746174757357616C6C6574417070 (hex)
|
* Data = 53746174757357616C6C6574417070 (hex)
|
||||||
* Response = The public key used to establish the SecureChannel
|
* Response = Application Info Template
|
||||||
|
|
||||||
|
Response Data format:
|
||||||
|
- Tag 0xA4 = Application Info Template
|
||||||
|
- Tag 0xC0 = Instance UID (16 bytes)
|
||||||
|
- Tag 0x80 = ECC public Key
|
||||||
|
|
||||||
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 public key which must
|
making it the active one. The data field is the AID of the application. The response is the Application Info template
|
||||||
be used by the client to establish the Secure Channel.
|
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.
|
||||||
|
|
||||||
### OPEN SECURE CHANNEL
|
### OPEN SECURE CHANNEL
|
||||||
|
|
||||||
|
|
|
@ -233,7 +233,7 @@ public class SecureChannel {
|
||||||
* @param off the offset in the buffer
|
* @param off the offset in the buffer
|
||||||
* @return the length of the public key
|
* @return the length of the public key
|
||||||
*/
|
*/
|
||||||
public short copyPublicKey(byte[] buf, byte off) {
|
public short copyPublicKey(byte[] buf, short off) {
|
||||||
ECPublicKey pk = (ECPublicKey) scKeypair.getPublic();
|
ECPublicKey pk = (ECPublicKey) scKeypair.getPublic();
|
||||||
return pk.getW(buf, off);
|
return pk.getW(buf, off);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ public class WalletApplet extends Applet {
|
||||||
static final byte PIN_MAX_RETRIES = 3;
|
static final byte PIN_MAX_RETRIES = 3;
|
||||||
static final byte KEY_PATH_MAX_DEPTH = 10;
|
static final byte KEY_PATH_MAX_DEPTH = 10;
|
||||||
static final byte PAIRING_MAX_CLIENT_COUNT = 5;
|
static final byte PAIRING_MAX_CLIENT_COUNT = 5;
|
||||||
|
static final byte UID_LENGTH = 16;
|
||||||
|
|
||||||
static final short EC_KEY_SIZE = 256;
|
static final short EC_KEY_SIZE = 256;
|
||||||
static final short CHAIN_CODE_SIZE = 32;
|
static final short CHAIN_CODE_SIZE = 32;
|
||||||
|
@ -70,11 +71,15 @@ public class WalletApplet extends Applet {
|
||||||
static final byte TLV_KEY_INITIALIZATION_STATUS = (byte) 0xC2;
|
static final byte TLV_KEY_INITIALIZATION_STATUS = (byte) 0xC2;
|
||||||
static final byte TLV_PUBLIC_KEY_DERIVATION = (byte) 0xC3;
|
static final byte TLV_PUBLIC_KEY_DERIVATION = (byte) 0xC3;
|
||||||
|
|
||||||
|
static final byte TLV_APPLICATION_INFO_TEMPLATE = (byte) 0xA4;
|
||||||
|
static final byte TLV_UID = (byte) 0xC0;
|
||||||
|
|
||||||
private static final byte[] ASSISTED_DERIVATION_HASH = {(byte) 0xAA, (byte) 0x2D, (byte) 0xA9, (byte) 0x9D, (byte) 0x91, (byte) 0x8C, (byte) 0x7D, (byte) 0x95, (byte) 0xB8, (byte) 0x96, (byte) 0x89, (byte) 0x87, (byte) 0x3E, (byte) 0xAA, (byte) 0x37, (byte) 0x67, (byte) 0x25, (byte) 0x0C, (byte) 0xFF, (byte) 0x50, (byte) 0x13, (byte) 0x9A, (byte) 0x2F, (byte) 0x87, (byte) 0xBB, (byte) 0x4F, (byte) 0xCA, (byte) 0xB4, (byte) 0xAE, (byte) 0xC3, (byte) 0xE8, (byte) 0x90};
|
private static final byte[] ASSISTED_DERIVATION_HASH = {(byte) 0xAA, (byte) 0x2D, (byte) 0xA9, (byte) 0x9D, (byte) 0x91, (byte) 0x8C, (byte) 0x7D, (byte) 0x95, (byte) 0xB8, (byte) 0x96, (byte) 0x89, (byte) 0x87, (byte) 0x3E, (byte) 0xAA, (byte) 0x37, (byte) 0x67, (byte) 0x25, (byte) 0x0C, (byte) 0xFF, (byte) 0x50, (byte) 0x13, (byte) 0x9A, (byte) 0x2F, (byte) 0x87, (byte) 0xBB, (byte) 0x4F, (byte) 0xCA, (byte) 0xB4, (byte) 0xAE, (byte) 0xC3, (byte) 0xE8, (byte) 0x90};
|
||||||
private static final byte[] WHISPER_KEY_PATH = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01};
|
private static final byte[] WHISPER_KEY_PATH = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01};
|
||||||
|
|
||||||
private OwnerPIN pin;
|
private OwnerPIN pin;
|
||||||
private OwnerPIN puk;
|
private OwnerPIN puk;
|
||||||
|
private byte[] uid;
|
||||||
private SecureChannel secureChannel;
|
private SecureChannel secureChannel;
|
||||||
|
|
||||||
private ECPublicKey masterPublic;
|
private ECPublicKey masterPublic;
|
||||||
|
@ -122,6 +127,9 @@ public class WalletApplet extends Applet {
|
||||||
Crypto.init();
|
Crypto.init();
|
||||||
SECP256k1.init();
|
SECP256k1.init();
|
||||||
|
|
||||||
|
uid = new byte[UID_LENGTH];
|
||||||
|
Crypto.random.generateData(uid, (short) 0, UID_LENGTH);
|
||||||
|
|
||||||
masterPublic = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, EC_KEY_SIZE, false);
|
masterPublic = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, EC_KEY_SIZE, false);
|
||||||
masterPrivate = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, EC_KEY_SIZE, false);
|
masterPrivate = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, EC_KEY_SIZE, false);
|
||||||
masterChainCode = new byte[CHAIN_CODE_SIZE];
|
masterChainCode = new byte[CHAIN_CODE_SIZE];
|
||||||
|
@ -246,8 +254,17 @@ public class WalletApplet extends Applet {
|
||||||
puk.reset();
|
puk.reset();
|
||||||
|
|
||||||
apdu.setIncomingAndReceive();
|
apdu.setIncomingAndReceive();
|
||||||
short keyLength = secureChannel.copyPublicKey(apdu.getBuffer(), ISO7816.OFFSET_CDATA);
|
byte[] apduBuffer = apdu.getBuffer();
|
||||||
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, keyLength);
|
|
||||||
|
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[1] = (byte)(keyLength + UID_LENGTH + 4);
|
||||||
|
apdu.setOutgoingAndSend((short) 0, (short)(apduBuffer[1] + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class WalletAppletTest {
|
||||||
void init() throws CardException {
|
void init() throws CardException {
|
||||||
reset();
|
reset();
|
||||||
cmdSet = new WalletAppletCommandSet(apduChannel);
|
cmdSet = new WalletAppletCommandSet(apduChannel);
|
||||||
byte[] keyData = cmdSet.select().getData();
|
byte[] keyData = extractPublicKeyFromSelect(cmdSet.select().getData());
|
||||||
secureChannel = new SecureChannelSession(keyData);
|
secureChannel = new SecureChannelSession(keyData);
|
||||||
cmdSet.setSecureChannel(secureChannel);
|
cmdSet.setSecureChannel(secureChannel);
|
||||||
cmdSet.autoPair(sha256("123456789012".getBytes()));
|
cmdSet.autoPair(sha256("123456789012".getBytes()));
|
||||||
|
@ -855,6 +855,14 @@ public class WalletAppletTest {
|
||||||
return Arrays.copyOfRange(sig, 5, 5 + sig[4]);
|
return Arrays.copyOfRange(sig, 5, 5 + sig[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] extractPublicKeyFromSelect(byte[] select) {
|
||||||
|
assertEquals(WalletApplet.TLV_APPLICATION_INFO_TEMPLATE, select[0]);
|
||||||
|
assertEquals(WalletApplet.TLV_UID, select[2]);
|
||||||
|
assertEquals(WalletApplet.TLV_PUB_KEY, select[20]);
|
||||||
|
|
||||||
|
return Arrays.copyOfRange(select, 22, select.length);
|
||||||
|
}
|
||||||
|
|
||||||
private void reset() {
|
private void reset() {
|
||||||
if (USE_SIMULATOR) {
|
if (USE_SIMULATOR) {
|
||||||
simulator.reset();
|
simulator.reset();
|
||||||
|
|
Loading…
Reference in New Issue