add instance UID

This commit is contained in:
Michele Balistreri 2017-11-15 12:55:41 +03:00
parent a61369d1bc
commit 09fe778d85
4 changed files with 38 additions and 7 deletions

View File

@ -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

View File

@ -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);
} }

View File

@ -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));
} }
/** /**

View File

@ -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();