add hint if public key derivation is optimized or not
This commit is contained in:
parent
d26b1120a0
commit
4c0c58ac90
|
@ -69,6 +69,7 @@ Response Data format:
|
||||||
- Tag 0xC0 = PIN retry count (1 byte)
|
- Tag 0xC0 = PIN retry count (1 byte)
|
||||||
- Tag 0xC1 = PUK retry count (1 byte)
|
- Tag 0xC1 = PUK retry count (1 byte)
|
||||||
- Tag 0xC2 = 0 if key is not initialized, 1 otherwise
|
- Tag 0xC2 = 0 if key is not initialized, 1 otherwise
|
||||||
|
- Tag 0xC3 = 1 if public key derivation is hw optimized, 0 otherwise
|
||||||
|
|
||||||
### VERIFY PIN
|
### VERIFY PIN
|
||||||
|
|
||||||
|
|
|
@ -90,4 +90,8 @@ public class SEC256k1 {
|
||||||
return ecPoint.getW(out, outOff);
|
return ecPoint.getW(out, outOff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean hasFastECPointMultiplication() {
|
||||||
|
return ecPointMultiplier != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ public class WalletApplet extends Applet {
|
||||||
static final byte TLV_PIN_RETRY_COUNT = (byte) 0xC0;
|
static final byte TLV_PIN_RETRY_COUNT = (byte) 0xC0;
|
||||||
static final byte TLV_PUK_RETRY_COUNT = (byte) 0xC1;
|
static final byte TLV_PUK_RETRY_COUNT = (byte) 0xC1;
|
||||||
static final byte TLV_KEY_INITIALIZATION_STATUS = (byte) 0xC2;
|
static final byte TLV_KEY_INITIALIZATION_STATUS = (byte) 0xC2;
|
||||||
|
static final byte TLV_FAST_PUBLIC_KEY_DERIVATION = (byte) 0xC3;
|
||||||
|
|
||||||
private OwnerPIN pin;
|
private OwnerPIN pin;
|
||||||
private OwnerPIN puk;
|
private OwnerPIN puk;
|
||||||
|
@ -175,6 +176,9 @@ public class WalletApplet extends Applet {
|
||||||
apduBuffer[off++] = TLV_KEY_INITIALIZATION_STATUS;
|
apduBuffer[off++] = TLV_KEY_INITIALIZATION_STATUS;
|
||||||
apduBuffer[off++] = 1;
|
apduBuffer[off++] = 1;
|
||||||
apduBuffer[off++] = privateKey.isInitialized() ? (byte) 0x01 : (byte) 0x00;
|
apduBuffer[off++] = privateKey.isInitialized() ? (byte) 0x01 : (byte) 0x00;
|
||||||
|
apduBuffer[off++] = TLV_FAST_PUBLIC_KEY_DERIVATION;
|
||||||
|
apduBuffer[off++] = 1;
|
||||||
|
apduBuffer[off++] = SEC256k1.hasFastECPointMultiplication() ? (byte) 0x01 : (byte) 0x00;
|
||||||
|
|
||||||
short len = secureChannel.encryptAPDU(apduBuffer, (short) (off - SecureChannel.SC_OUT_OFFSET));
|
short len = secureChannel.encryptAPDU(apduBuffer, (short) (off - SecureChannel.SC_OUT_OFFSET));
|
||||||
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len);
|
apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA, len);
|
||||||
|
|
|
@ -117,24 +117,25 @@ public class WalletAppletTest {
|
||||||
cmdSet.openSecureChannel();
|
cmdSet.openSecureChannel();
|
||||||
|
|
||||||
// Good case. Since the order of test execution is undefined, the test cannot know if the keys are initialized or not.
|
// Good case. Since the order of test execution is undefined, the test cannot know if the keys are initialized or not.
|
||||||
|
// Additionally, support for fast public key derivation is hw dependent.
|
||||||
response = cmdSet.getStatus();
|
response = cmdSet.getStatus();
|
||||||
assertEquals(0x9000, response.getSW());
|
assertEquals(0x9000, response.getSW());
|
||||||
byte[] data = secureChannel.decryptAPDU(response.getData());
|
byte[] data = secureChannel.decryptAPDU(response.getData());
|
||||||
assertTrue(Hex.toHexString(data).matches("a309c00103c10105c2010[0-1]"));
|
assertTrue(Hex.toHexString(data).matches("a309c00103c10105c2010[0-1]c3010[0-1]"));
|
||||||
|
|
||||||
response = cmdSet.verifyPIN("123456");
|
response = cmdSet.verifyPIN("123456");
|
||||||
assertEquals(0x63C2, response.getSW());
|
assertEquals(0x63C2, response.getSW());
|
||||||
response = cmdSet.getStatus();
|
response = cmdSet.getStatus();
|
||||||
assertEquals(0x9000, response.getSW());
|
assertEquals(0x9000, response.getSW());
|
||||||
data = secureChannel.decryptAPDU(response.getData());
|
data = secureChannel.decryptAPDU(response.getData());
|
||||||
assertTrue(Hex.toHexString(data).matches("a309c00102c10105c2010[0-1]"));
|
assertTrue(Hex.toHexString(data).matches("a309c00102c10105c2010[0-1]c3010[0-1]"));
|
||||||
|
|
||||||
response = cmdSet.verifyPIN("000000");
|
response = cmdSet.verifyPIN("000000");
|
||||||
assertEquals(0x9000, response.getSW());
|
assertEquals(0x9000, response.getSW());
|
||||||
response = cmdSet.getStatus();
|
response = cmdSet.getStatus();
|
||||||
assertEquals(0x9000, response.getSW());
|
assertEquals(0x9000, response.getSW());
|
||||||
data = secureChannel.decryptAPDU(response.getData());
|
data = secureChannel.decryptAPDU(response.getData());
|
||||||
assertTrue(Hex.toHexString(data).matches("a309c00103c10105c2010[0-1]"));
|
assertTrue(Hex.toHexString(data).matches("a309c00103c10105c2010[0-1]c3010[0-1]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -396,14 +397,21 @@ public class WalletAppletTest {
|
||||||
response = cmdSet.sign(data, WalletApplet.SIGN_P1_DATA,false, true);
|
response = cmdSet.sign(data, WalletApplet.SIGN_P1_DATA,false, true);
|
||||||
assertEquals(0x6A86, response.getSW());
|
assertEquals(0x6A86, response.getSW());
|
||||||
|
|
||||||
// Correctly sign 1 block (P2: 0x81)
|
// Correctly sign a precomputed hash
|
||||||
response = cmdSet.sign(smallData, WalletApplet.SIGN_P1_DATA,true, true);
|
MessageDigest md = MessageDigest.getInstance("SHA-256", "BC");
|
||||||
|
response = cmdSet.sign(md.digest(data), WalletApplet.SIGN_P1_PRECOMPUTED_HASH,true, true);
|
||||||
assertEquals(0x9000, response.getSW());
|
assertEquals(0x9000, response.getSW());
|
||||||
byte[] sig = secureChannel.decryptAPDU(response.getData());
|
byte[] sig = secureChannel.decryptAPDU(response.getData());
|
||||||
byte[] keyData = extractPublicKey(sig);
|
byte[] keyData = extractPublicKey(sig);
|
||||||
sig = extractSignature(sig);
|
sig = extractSignature(sig);
|
||||||
assertEquals((SecureChannel.SC_KEY_LENGTH * 2 / 8) + 1, keyData.length);
|
assertEquals((SecureChannel.SC_KEY_LENGTH * 2 / 8) + 1, keyData.length);
|
||||||
|
signature.update(data);
|
||||||
|
assertTrue(signature.verify(sig));
|
||||||
|
|
||||||
|
// Correctly sign 1 block (P2: 0x81)
|
||||||
|
response = cmdSet.sign(smallData, WalletApplet.SIGN_P1_DATA,true, true);
|
||||||
|
assertEquals(0x9000, response.getSW());
|
||||||
|
sig = extractSignature(secureChannel.decryptAPDU(response.getData()));
|
||||||
signature.update(smallData);
|
signature.update(smallData);
|
||||||
assertTrue(signature.verify(sig));
|
assertTrue(signature.verify(sig));
|
||||||
|
|
||||||
|
@ -469,14 +477,6 @@ public class WalletAppletTest {
|
||||||
signature.update(data);
|
signature.update(data);
|
||||||
signature.update(smallData);
|
signature.update(smallData);
|
||||||
assertTrue(signature.verify(sig));
|
assertTrue(signature.verify(sig));
|
||||||
|
|
||||||
MessageDigest md = MessageDigest.getInstance("SHA-256", "BC");
|
|
||||||
response = cmdSet.sign(md.digest(data), WalletApplet.SIGN_P1_PRECOMPUTED_HASH,true, true);
|
|
||||||
assertEquals(0x9000, response.getSW());
|
|
||||||
sig = extractSignature(secureChannel.decryptAPDU(response.getData()));
|
|
||||||
signature.update(data);
|
|
||||||
assertTrue(signature.verify(sig));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue