JCOP4 workaround (defer initialization)

This commit is contained in:
Michele Balistreri 2020-01-23 19:05:49 +03:00
parent bca030f069
commit 1d16a82117
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
6 changed files with 15 additions and 26 deletions

View File

@ -64,11 +64,11 @@ public class InstallTask extends DefaultTask {
}
});
logger.info("Installing the Keycard Applet");
cmdSet.installKeycardApplet();
cmdSet.installKeycardApplet().checkOK();
logger.info("Installing the NDEF Applet");
cmdSet.installNDEFApplet(new byte[0]);
cmdSet.installNDEFApplet(new byte[0]).checkOK();
logger.info("Installing the Cash Applet");
cmdSet.installCashApplet();
cmdSet.installCashApplet().checkOK();
} catch (IOException e) {
throw new GradleException("I/O error", e);
} catch (APDUException e) {

View File

@ -40,7 +40,7 @@ public class CashApplet extends Applet {
*/
public CashApplet(byte[] bArray, short bOffset, byte bLength) {
crypto = new Crypto();
secp256k1 = new SECP256k1(crypto);
secp256k1 = new SECP256k1();
keypair = new KeyPair(KeyPair.ALG_EC_FP, SECP256k1.SECP256K1_KEY_SIZE);
publicKey = (ECPublicKey) keypair.getPublic();

View File

@ -167,8 +167,7 @@ public class KeycardApplet extends Applet {
*/
public KeycardApplet(byte[] bArray, short bOffset, byte bLength) {
crypto = new Crypto();
secp256k1 = new SECP256k1(crypto);
secureChannel = new SecureChannel(PAIRING_MAX_CLIENT_COUNT, crypto, secp256k1);
secp256k1 = new SECP256k1();
uid = new byte[UID_LENGTH];
crypto.random.generateData(uid, (short) 0, UID_LENGTH);
@ -199,7 +198,7 @@ public class KeycardApplet extends Applet {
derivationOutput = JCSystem.makeTransientByteArray((short) (Crypto.KEY_SECRET_SIZE + CHAIN_CODE_SIZE), JCSystem.CLEAR_ON_RESET);
data = new byte[MAX_DATA_LENGTH + 1];
data = new byte[(short)(MAX_DATA_LENGTH + 1)];
register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}
@ -214,6 +213,9 @@ public class KeycardApplet extends Applet {
public void process(APDU apdu) throws ISOException {
// If we have no PIN it means we still have to initialize the applet.
if (pin == null) {
if (secureChannel == null) {
secureChannel = new SecureChannel(PAIRING_MAX_CLIENT_COUNT, crypto, secp256k1);
}
processInit(apdu);
return;
}

View File

@ -54,14 +54,12 @@ public class SECP256k1 {
private KeyAgreement ecPointMultiplier;
private Crypto crypto;
ECPrivateKey tmpECPrivateKey;
/**
* Allocates objects needed by this class. Must be invoked during the applet installation exactly 1 time.
*/
SECP256k1(Crypto crypto) {
this.crypto = crypto;
SECP256k1() {
this.ecPointMultiplier = KeyAgreement.getInstance(ALG_EC_SVDP_DH_PLAIN_XY, false);
this.tmpECPrivateKey = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, SECP256K1_KEY_SIZE, false);
setCurveParameters(tmpECPrivateKey);

View File

@ -56,13 +56,14 @@ public class SecureChannel {
scEncKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
scMacKey = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_DESELECT, KeyBuilder.LENGTH_AES_256, false);
secret = JCSystem.makeTransientByteArray((short)(SC_SECRET_LENGTH * 2), JCSystem.CLEAR_ON_DESELECT);
pairingKeys = new byte[(short)(PAIRING_KEY_LENGTH * pairingLimit)];
scKeypair = new KeyPair(KeyPair.ALG_EC_FP, SC_KEY_LENGTH);
secp256k1.setCurveParameters((ECKey) scKeypair.getPrivate());
secp256k1.setCurveParameters((ECKey) scKeypair.getPublic());
scKeypair.genKeyPair();
secret = JCSystem.makeTransientByteArray((short)(SC_SECRET_LENGTH * 2), JCSystem.CLEAR_ON_DESELECT);
pairingKeys = new byte[(short)(PAIRING_KEY_LENGTH * pairingLimit)];
remainingSlots = pairingLimit;
}

View File

@ -289,19 +289,7 @@ public class KeycardTest {
response = cmdSet.getStatus(KeycardApplet.GET_STATUS_P1_APPLICATION);
assertEquals(0x9000, response.getSw());
// 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 = new ApplicationInfo(cmdSet.select().getData()).getSecureChannelPubKey();
for (int i = 0; i < SecureChannel.SC_COUNTER_MAX; i++) {
byte[] otherKey = new ApplicationInfo(cmdSet.select().getData()).getSecureChannelPubKey();
if (!Arrays.equals(initialKey, otherKey)) {
secureChannel.generateSecret(otherKey);
cmdSet.autoOpenSecureChannel();
break;
}
}
}
@Test
@ -384,7 +372,7 @@ public class KeycardTest {
cmdSet.openSecureChannel(secureChannel.getPairingIndex(), secureChannel.getPublicKey());
// Pair multiple indexes
for (int i = 1; i < 5; i++) {
for (int i = 1; i < KeycardApplet.PAIRING_MAX_CLIENT_COUNT; i++) {
cmdSet.autoPair(sharedSecret);
assertEquals(i, secureChannel.getPairingIndex());
cmdSet.autoOpenSecureChannel();
@ -403,7 +391,7 @@ public class KeycardTest {
assertEquals(0x9000, response.getSw());
}
for (byte i = 0; i < 4; i++) {
for (byte i = 0; i < (KeycardApplet.PAIRING_MAX_CLIENT_COUNT - 1); i++) {
response = cmdSet.unpair(i);
assertEquals(0x9000, response.getSw());
}