add pinless path caching
This commit is contained in:
parent
8f1461e33a
commit
ec121e477d
|
@ -113,6 +113,9 @@ public class KeycardApplet extends Applet {
|
||||||
private ECPrivateKey privateKey;
|
private ECPrivateKey privateKey;
|
||||||
private byte[] chainCode;
|
private byte[] chainCode;
|
||||||
|
|
||||||
|
private ECPublicKey pinlessPublicKey;
|
||||||
|
private ECPrivateKey pinlessPrivateKey;
|
||||||
|
|
||||||
private byte[] keyPath;
|
private byte[] keyPath;
|
||||||
private short keyPathLen;
|
private short keyPathLen;
|
||||||
|
|
||||||
|
@ -171,6 +174,9 @@ public class KeycardApplet extends Applet {
|
||||||
publicKey = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, SECP256k1.SECP256K1_KEY_SIZE, false);
|
publicKey = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, SECP256k1.SECP256K1_KEY_SIZE, false);
|
||||||
privateKey = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, SECP256k1.SECP256K1_KEY_SIZE, false);
|
privateKey = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, SECP256k1.SECP256K1_KEY_SIZE, false);
|
||||||
|
|
||||||
|
pinlessPublicKey = (ECPublicKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PUBLIC, SECP256k1.SECP256K1_KEY_SIZE, false);
|
||||||
|
pinlessPrivateKey = (ECPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_EC_FP_PRIVATE, SECP256k1.SECP256K1_KEY_SIZE, false);
|
||||||
|
|
||||||
masterChainCode = new byte[CHAIN_CODE_SIZE];
|
masterChainCode = new byte[CHAIN_CODE_SIZE];
|
||||||
parentChainCode = new byte[CHAIN_CODE_SIZE];
|
parentChainCode = new byte[CHAIN_CODE_SIZE];
|
||||||
chainCode = new byte[CHAIN_CODE_SIZE];
|
chainCode = new byte[CHAIN_CODE_SIZE];
|
||||||
|
@ -646,6 +652,7 @@ public class KeycardApplet extends Applet {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pinlessPathLen = 0;
|
||||||
generateKeyUIDAndRespond(apdu, apduBuffer);
|
generateKeyUIDAndRespond(apdu, apduBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1030,6 +1037,8 @@ public class KeycardApplet extends Applet {
|
||||||
masterPublic.clearKey();
|
masterPublic.clearKey();
|
||||||
parentPrivateKey.clearKey();
|
parentPrivateKey.clearKey();
|
||||||
parentPublicKey.clearKey();
|
parentPublicKey.clearKey();
|
||||||
|
pinlessPrivateKey.clearKey();
|
||||||
|
pinlessPublicKey.clearKey();
|
||||||
resetCurveParameters();
|
resetCurveParameters();
|
||||||
Util.arrayFillNonAtomic(chainCode, (short) 0, (short) chainCode.length, (byte) 0);
|
Util.arrayFillNonAtomic(chainCode, (short) 0, (short) chainCode.length, (byte) 0);
|
||||||
Util.arrayFillNonAtomic(parentChainCode, (short) 0, (short) parentChainCode.length, (byte) 0);
|
Util.arrayFillNonAtomic(parentChainCode, (short) 0, (short) parentChainCode.length, (byte) 0);
|
||||||
|
@ -1057,6 +1066,7 @@ public class KeycardApplet extends Applet {
|
||||||
crypto.random.generateData(apduBuffer, ISO7816.OFFSET_CDATA, BIP39_SEED_SIZE);
|
crypto.random.generateData(apduBuffer, ISO7816.OFFSET_CDATA, BIP39_SEED_SIZE);
|
||||||
|
|
||||||
loadSeed(apduBuffer);
|
loadSeed(apduBuffer);
|
||||||
|
pinlessPathLen = 0;
|
||||||
generateKeyUIDAndRespond(apdu, apduBuffer);
|
generateKeyUIDAndRespond(apdu, apduBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1094,6 +1104,7 @@ public class KeycardApplet extends Applet {
|
||||||
break;
|
break;
|
||||||
case DUPLICATE_KEY_P1_IMPORT:
|
case DUPLICATE_KEY_P1_IMPORT:
|
||||||
importDuplicate(apduBuffer);
|
importDuplicate(apduBuffer);
|
||||||
|
pinlessPathLen = 0;
|
||||||
generateKeyUIDAndRespond(apdu, apduBuffer);
|
generateKeyUIDAndRespond(apdu, apduBuffer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1231,6 +1242,14 @@ public class KeycardApplet extends Applet {
|
||||||
JCSystem.beginTransaction();
|
JCSystem.beginTransaction();
|
||||||
pinlessPathLen = len;
|
pinlessPathLen = len;
|
||||||
Util.arrayCopy(apduBuffer, ISO7816.OFFSET_CDATA, pinlessPath, (short) 0, len);
|
Util.arrayCopy(apduBuffer, ISO7816.OFFSET_CDATA, pinlessPath, (short) 0, len);
|
||||||
|
|
||||||
|
if (pinlessPathLen > 0) {
|
||||||
|
doDerive(apduBuffer, len, DERIVE_P1_SOURCE_MASTER, false);
|
||||||
|
pinlessPrivateKey.setS(derivationOutput, (short) 0, Crypto.KEY_SECRET_SIZE);
|
||||||
|
secp256k1.derivePublicKey(pinlessPrivateKey, apduBuffer, (short) 0);
|
||||||
|
pinlessPublicKey.setW(apduBuffer, (short) 0, Crypto.KEY_PUB_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
JCSystem.commitTransaction();
|
JCSystem.commitTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1379,5 +1398,8 @@ public class KeycardApplet extends Applet {
|
||||||
|
|
||||||
secp256k1.setCurveParameters(publicKey);
|
secp256k1.setCurveParameters(publicKey);
|
||||||
secp256k1.setCurveParameters(privateKey);
|
secp256k1.setCurveParameters(privateKey);
|
||||||
|
|
||||||
|
secp256k1.setCurveParameters(pinlessPrivateKey);
|
||||||
|
secp256k1.setCurveParameters(pinlessPublicKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class SECP256k1 {
|
||||||
|
|
||||||
private KeyAgreement ecPointMultiplier;
|
private KeyAgreement ecPointMultiplier;
|
||||||
private Crypto crypto;
|
private Crypto crypto;
|
||||||
private ECPrivateKey tmpECPrivateKey;
|
ECPrivateKey tmpECPrivateKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates objects needed by this class. Must be invoked during the applet installation exactly 1 time.
|
* Allocates objects needed by this class. Must be invoked during the applet installation exactly 1 time.
|
||||||
|
|
|
@ -1082,12 +1082,19 @@ public class KeycardTest {
|
||||||
resetAndSelectAndOpenSC();
|
resetAndSelectAndOpenSC();
|
||||||
response = cmdSet.sign(hash);
|
response = cmdSet.sign(hash);
|
||||||
assertEquals(0x6985, response.getSw());
|
assertEquals(0x6985, response.getSw());
|
||||||
|
|
||||||
|
if (cmdSet.getApplicationInfo().hasCredentialsManagementCapability()) {
|
||||||
|
response = cmdSet.verifyPIN("000000");
|
||||||
|
assertEquals(0x9000, response.getSw());
|
||||||
|
}
|
||||||
|
|
||||||
response = cmdSet.deriveKey(new byte[] {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01}, KeycardApplet.DERIVE_P1_SOURCE_MASTER);
|
response = cmdSet.deriveKey(new byte[] {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01}, KeycardApplet.DERIVE_P1_SOURCE_MASTER);
|
||||||
assertEquals(0x9000, response.getSw());
|
assertEquals(0x9000, response.getSw());
|
||||||
response = cmdSet.sign(hash);
|
|
||||||
assertEquals(0x6985, response.getSw());
|
|
||||||
response = cmdSet.deriveKey(new byte[] {0x00, 0x00, 0x00, 0x02}, KeycardApplet.DERIVE_P1_SOURCE_CURRENT);
|
response = cmdSet.deriveKey(new byte[] {0x00, 0x00, 0x00, 0x02}, KeycardApplet.DERIVE_P1_SOURCE_CURRENT);
|
||||||
assertEquals(0x9000, response.getSw());
|
assertEquals(0x9000, response.getSw());
|
||||||
|
|
||||||
|
resetAndSelectAndOpenSC();
|
||||||
|
|
||||||
response = cmdSet.sign(hash);
|
response = cmdSet.sign(hash);
|
||||||
assertEquals(0x9000, response.getSw());
|
assertEquals(0x9000, response.getSw());
|
||||||
|
|
||||||
|
@ -1102,8 +1109,16 @@ public class KeycardTest {
|
||||||
resetAndSelectAndOpenSC();
|
resetAndSelectAndOpenSC();
|
||||||
response = cmdSet.sign(hash);
|
response = cmdSet.sign(hash);
|
||||||
assertEquals(0x6985, response.getSw());
|
assertEquals(0x6985, response.getSw());
|
||||||
|
|
||||||
|
|
||||||
|
if (cmdSet.getApplicationInfo().hasCredentialsManagementCapability()) {
|
||||||
|
response = cmdSet.verifyPIN("000000");
|
||||||
|
assertEquals(0x9000, response.getSw());
|
||||||
|
}
|
||||||
|
|
||||||
response = cmdSet.deriveKey(new byte[] {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01}, KeycardApplet.DERIVE_P1_SOURCE_MASTER);
|
response = cmdSet.deriveKey(new byte[] {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01}, KeycardApplet.DERIVE_P1_SOURCE_MASTER);
|
||||||
assertEquals(0x9000, response.getSw());
|
assertEquals(0x9000, response.getSw());
|
||||||
|
resetAndSelectAndOpenSC();
|
||||||
response = cmdSet.sign(hash);
|
response = cmdSet.sign(hash);
|
||||||
assertEquals(0x9000, response.getSw());
|
assertEquals(0x9000, response.getSw());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue