make EXPORT KEY able to derive from other sources

This commit is contained in:
Michele Balistreri 2018-11-30 11:34:05 +03:00
parent 98ffcda1b8
commit d4e01ab21b
4 changed files with 20 additions and 16 deletions

View File

@ -439,7 +439,9 @@ private key (P2=0x00) can be exported if and only if the requested key path is i
The P1 parameter indicates how to the derive the desired key. P1 = 0x00 indicates that the current key must be exported,
and no derivation will be performed. P1 = 0x01 derives the path given in the data field without changing the current
path of the card. P1 = 0x02 derives the path but also changes the current path of the card.
path of the card. P1 = 0x02 derives the path but also changes the current path of the card. The source for derivation
can be set by OR'ing P1 with the constants defined in the DERIVE KEY command. This allows deriving from master, parent
or current.
If the private key is being exported, the card could omit exporting the public key for performance reason. The public
key can then be calculate off-card if needed.

View File

@ -42,7 +42,7 @@ dependencies {
testCompile('org.web3j:core:2.3.1')
testCompile('org.bitcoinj:bitcoinj-core:0.14.5')
testCompile("org.bouncycastle:bcprov-jdk15on:1.58")
testCompile("com.github.status-im:hardwallet-lite-sdk:75d9f54")
testCompile("com.github.status-im:hardwallet-lite-sdk:482e32c")
testCompile("org.junit.jupiter:junit-jupiter-api:5.1.1")
testRuntime("org.junit.jupiter:junit-jupiter-engine:5.1.1")
}

View File

@ -52,6 +52,7 @@ public class WalletApplet extends Applet {
static final byte DERIVE_P1_SOURCE_MASTER = (byte) 0x00;
static final byte DERIVE_P1_SOURCE_PARENT = (byte) 0x40;
static final byte DERIVE_P1_SOURCE_CURRENT = (byte) 0x80;
static final byte DERIVE_P1_SOURCE_MASK = (byte) 0xC0;
static final byte GENERATE_MNEMONIC_P1_CS_MIN = 4;
static final byte GENERATE_MNEMONIC_P1_CS_MAX = 8;
@ -1233,25 +1234,26 @@ public class WalletApplet extends Applet {
return;
}
byte[] exportPath;
short exportPathOff;
short exportPathLen;
byte[] exportPath = keyPath;
short exportPathOff = (short) 0;
short exportPathLen = keyPathLen;
boolean derive = false;
boolean makeCurrent = false;
byte derivationSource = (byte) (apduBuffer[ISO7816.OFFSET_P1] & DERIVE_P1_SOURCE_MASK);
switch (apduBuffer[ISO7816.OFFSET_P1]) {
switch ((byte) (apduBuffer[ISO7816.OFFSET_P1] & ~DERIVE_P1_SOURCE_MASK)) {
case EXPORT_KEY_P1_CURRENT:
exportPath = keyPath;
exportPathOff = (short) 0;
exportPathLen = keyPathLen;
break;
case EXPORT_KEY_P1_DERIVE_AND_MAKE_CURRENT:
makeCurrent = true;
case EXPORT_KEY_P1_DERIVE:
derive = true;
exportPath = apduBuffer;
exportPathOff = ISO7816.OFFSET_CDATA;
exportPathLen = dataLen;
if (derivationSource == DERIVE_P1_SOURCE_MASTER) {
exportPath = apduBuffer;
exportPathOff = ISO7816.OFFSET_CDATA;
exportPathLen = dataLen;
}
break;
default:
ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
@ -1263,7 +1265,7 @@ public class WalletApplet extends Applet {
}
if (derive) {
doDerive(apduBuffer, dataLen, DERIVE_P1_SOURCE_MASTER, makeCurrent);
doDerive(apduBuffer, dataLen, derivationSource, makeCurrent);
}
short off = SecureChannel.SC_OUT_OFFSET;

View File

@ -981,13 +981,13 @@ public class WalletAppletTest {
verifyExportedKey(keyTemplate, keyPair, chainCode, new int[] { 0x8000002b, 0x8000003c, 0x8000062d, 0x00000000 }, true, false);
// Derive & Make current
response = cmdSet.exportKey(new byte[] {(byte) 0x80, 0x00, 0x00, 0x2B, (byte) 0x80, 0x00, 0x00, 0x3C, (byte) 0x80, 0x00, 0x06, 0x2D, (byte) 0x00, 0x00, 0x00, 0x00, (byte) 0x00, 0x00, 0x00, 0x00}, true,false);
response = cmdSet.exportKey(new byte[] {(byte) 0x80, 0x00, 0x00, 0x2B, (byte) 0x80, 0x00, 0x00, 0x3C, (byte) 0x80, 0x00, 0x06, 0x2D, (byte) 0x00, 0x00, 0x00, 0x00, (byte) 0x00, 0x00, 0x00, 0x00}, WalletApplet.DERIVE_P1_SOURCE_MASTER,true,false);
assertEquals(0x9000, response.getSW());
keyTemplate = response.getData();
verifyExportedKey(keyTemplate, keyPair, chainCode, new int[] { 0x8000002b, 0x8000003c, 0x8000062d, 0x00000000, 0x00000000 }, false, false);
// Derive without making current
response = cmdSet.exportKey(new byte[] {(byte) 0x80, 0x00, 0x00, 0x2B, (byte) 0x80, 0x00, 0x00, 0x3C, (byte) 0x80, 0x00, 0x06, 0x2D, (byte) 0x00, 0x00, 0x00, 0x00, (byte) 0x00, 0x00, 0x00, 0x01}, false,false);
response = cmdSet.exportKey(new byte[] {(byte) 0x00, 0x00, 0x00, 0x01}, WalletApplet.DERIVE_P1_SOURCE_PARENT, false,false);
assertEquals(0x9000, response.getSW());
keyTemplate = response.getData();
verifyExportedKey(keyTemplate, keyPair, chainCode, new int[] { 0x8000002b, 0x8000003c, 0x8000062d, 0x00000000, 0x00000001 }, false, true);
@ -1002,7 +1002,7 @@ public class WalletAppletTest {
verifyExportedKey(keyTemplate, keyPair, chainCode, new int[] { 0x8000002b, 0x8000003c, 0x8000062d, 0x00000000, 0x00000000 }, false, false);
// Reset
response = cmdSet.deriveKey(new byte[] {}, WalletApplet.DERIVE_P1_SOURCE_MASTER);
response = cmdSet.deriveKey(new byte[0], WalletApplet.DERIVE_P1_SOURCE_MASTER);
assertEquals(0x9000, response.getSW());
}