add pinless path caching

This commit is contained in:
Michele Balistreri 2019-03-28 10:50:29 +03:00
parent 8f1461e33a
commit ec121e477d
3 changed files with 40 additions and 3 deletions

View File

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

View File

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

View File

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