simplify specifications - public key derivation must be somehow implemented

This commit is contained in:
Michele Balistreri 2017-10-11 10:55:04 +03:00
parent 5be35a8fe1
commit 97d195e6b5
3 changed files with 11 additions and 34 deletions

View File

@ -69,7 +69,6 @@ Response Data format:
- Tag 0xC0 = PIN retry count (1 byte)
- Tag 0xC1 = PUK retry count (1 byte)
- Tag 0xC2 = 0 if key is not initialized, 1 otherwise
- Tag 0xC3 = 0 if public key derivation is not supported, 1 otherwise
### VERIFY PIN
@ -125,27 +124,24 @@ always returns 0x63C0, even if the PUK is inserted correctly. In this case the w
* P1 = key type
* P2 = 0x00
* Data = the key data
* Response SW = 0x9000 on success, 0x6A80 if the format is invalid, 0x6A86 if P1 is invalid, 0x6A81 if public key is
omitted and its derivation is not supported.
* Response SW = 0x9000 on success, 0x6A80 if the format is invalid, 0x6A86 if P1 is invalid
* Preconditions: Secure Channel must be opened, user PIN must be verified
P1:
* 0x01 = ECC SECP256k1 keypair
* 0x02 = ECC SECP256k1 extended keypair
* 0x03 = Binary seed as defined in [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) (if card
supports public key derivation)
* 0x03 = Binary seed as defined in [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
Data:
If P1 is 0x01 or 0x02
- Tag 0xA1 = keypair template
- Tag 0x80 = ECC public key component (can be omitted if card supports public key derivation)
- Tag 0x80 = ECC public key component (can be omitted)
- Tag 0x81 = ECC private key component
- Tag 0x82 = chain code (if P1=0x02)
If P1 is 0x03 a 64 byte sequence generated according to the BIP39 specifications is expected. The master key will be
generated according to the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) specifications. Since
in this case the public key is not provided externally, the card must support public key derivation.
generated according to the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) specifications.
This command is used to load or replace the keypair used for signing on the card. This command always aborts open
signing sessions, if any. Unless a DERIVE KEY is sent, a subsequent SIGN command will use this keypair for signature.
@ -156,21 +152,12 @@ signing sessions, if any. Unless a DERIVE KEY is sent, a subsequent SIGN command
* INS = 0xD1
* P1 = 0x00
* P2 = 0x00
* Data = key derivation template
* Response SW = 0x9000 on success, 0x6A80 if the format is invalid, 0x6A81 if public keys are omitted and their derivation
is not supported.
* Data = a sequence of 32-bit integers (most significant byte first). Empty if the master key must be used.
* Response SW = 0x9000 on success, 0x6A80 if the format is invalid
* Preconditions: Secure Channel must be opened, user PIN must be verified, an extended keyset must be loaded
Data format:
- Tag 0xA2 = key derivation template
- Tag 0xC0 = a sequence of 32-bit integers (most significant byte first). Empty if the master key must be used.
- Tag 0xC1 = derived public key (omitted if master or public key derivation is supported)
- Tag 0xC2 = parent public key (omitted if master or public key derivation is supported)
This command is used before a signing session to generated a private key according to the [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
specifications. The generated key is used for all subsequent SIGN sessions. An empty 0x82 is used in order for SIGN to
use the master key instead. Omitting the 0x82 subtag entirely is not permitted.
specifications. The generated key is used for all subsequent SIGN sessions.
### GENERATE MNEMONIC

View File

@ -43,16 +43,10 @@ public class WalletApplet extends Applet {
static final byte TLV_PRIV_KEY = (byte) 0x81;
static final byte TLV_CHAIN_CODE = (byte) 0x82;
static final byte TLV_KEY_DERIVATION_TEMPLATE = (byte) 0xA2;
static final byte TLV_DERIVATION_SEQUENCE = (byte) 0xC0;
static final byte TLV_DERIVED_PUB_KEY = (byte) 0xC1;
static final byte TLV_PARENT_PUB_KEY = (byte) 0xC2;
static final byte TLV_APPLICATION_STATUS_TEMPLATE = (byte) 0xA3;
static final byte TLV_PIN_RETRY_COUNT = (byte) 0xC0;
static final byte TLV_PUK_RETRY_COUNT = (byte) 0xC1;
static final byte TLV_KEY_INITIALIZATION_STATUS = (byte) 0xC2;
static final byte TLV_PUBLIC_KEY_DERIVATION_SUPPORTED = (byte) 0xC3;
private OwnerPIN pin;
private OwnerPIN puk;
@ -168,7 +162,7 @@ public class WalletApplet extends Applet {
byte[] apduBuffer = apdu.getBuffer();
apduBuffer[off++] = TLV_APPLICATION_STATUS_TEMPLATE;
apduBuffer[off++] = 12;
apduBuffer[off++] = 9;
apduBuffer[off++] = TLV_PIN_RETRY_COUNT;
apduBuffer[off++] = 1;
apduBuffer[off++] = pin.getTriesRemaining();
@ -178,9 +172,6 @@ public class WalletApplet extends Applet {
apduBuffer[off++] = TLV_KEY_INITIALIZATION_STATUS;
apduBuffer[off++] = 1;
apduBuffer[off++] = privateKey.isInitialized() ? (byte) 0x01 : (byte) 0x00;
apduBuffer[off++] = TLV_PUBLIC_KEY_DERIVATION_SUPPORTED;
apduBuffer[off++] = 1;
apduBuffer[off++] = 1; //TODO: actually check if it is supported or totally remove if a fallback software implementation is a requirement
short len = secureChannel.encryptAPDU(apduBuffer, (short) (off - SecureChannel.SC_OUT_OFFSET));
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len);

View File

@ -116,25 +116,24 @@ public class WalletAppletTest {
cmdSet.openSecureChannel();
// Good case. Since the order of test execution is undefined, the test cannot know if the keys are initialized or not.
// Additionally, the public key derivation cannot also be known here.
response = cmdSet.getStatus();
assertEquals(0x9000, response.getSW());
byte[] data = secureChannel.decryptAPDU(response.getData());
assertTrue(Hex.toHexString(data).matches("a30cc00103c10105c2010[0-1]c3010[0-1]"));
assertTrue(Hex.toHexString(data).matches("a309c00103c10105c2010[0-1]"));
response = cmdSet.verifyPIN("123456");
assertEquals(0x63C2, response.getSW());
response = cmdSet.getStatus();
assertEquals(0x9000, response.getSW());
data = secureChannel.decryptAPDU(response.getData());
assertTrue(Hex.toHexString(data).matches("a30cc00102c10105c2010[0-1]c3010[0-1]"));
assertTrue(Hex.toHexString(data).matches("a309c00102c10105c2010[0-1]"));
response = cmdSet.verifyPIN("000000");
assertEquals(0x9000, response.getSW());
response = cmdSet.getStatus();
assertEquals(0x9000, response.getSW());
data = secureChannel.decryptAPDU(response.getData());
assertTrue(Hex.toHexString(data).matches("a30cc00103c10105c2010[0-1]c3010[0-1]"));
assertTrue(Hex.toHexString(data).matches("a309c00103c10105c2010[0-1]"));
}
@Test