implement UNBLOCK PIN

This commit is contained in:
Michele Balistreri 2017-09-27 19:49:02 +03:00
parent f05190111c
commit 91b4a96194
3 changed files with 69 additions and 5 deletions

View File

@ -16,7 +16,6 @@ public class WalletApplet extends Applet {
static final byte PIN_LENGTH = 6;
static final byte PIN_MAX_RETRIES = 3;
static final short TMP_BUFFER_LENGTH = PIN_LENGTH;
static final short EC_KEY_SIZE = 256;
@ -30,8 +29,8 @@ public class WalletApplet extends Applet {
}
public WalletApplet(byte[] bArray, short bOffset, byte bLength) {
short c9Off = (short)(bOffset + bArray[bOffset] + 1);
c9Off += (short)(bArray[bOffset] + 1 + 2);
short c9Off = (short)(bOffset + bArray[bOffset] + 1); // Skip AID
c9Off += (short)(bArray[c9Off] + 2); // Skip Privileges and parameter length
puk = new OwnerPIN(PUK_MAX_RETRIES, PUK_LENGTH);
puk.update(bArray, c9Off, PUK_LENGTH);
@ -112,7 +111,7 @@ public class WalletApplet extends Applet {
byte[] apduBuffer = apdu.getBuffer();
byte len = secureChannel.decryptAPDU(apduBuffer);
if (!(len == 6 && allDigits(apduBuffer, ISO7816.OFFSET_CDATA, len))) {
if (!(len == PIN_LENGTH && allDigits(apduBuffer, ISO7816.OFFSET_CDATA, len))) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
}
@ -126,6 +125,22 @@ public class WalletApplet extends Applet {
if (!(secureChannel.isOpen() && pin.getTriesRemaining() == 0)) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
byte[] apduBuffer = apdu.getBuffer();
byte len = secureChannel.decryptAPDU(apduBuffer);
if (!(len == (PUK_LENGTH + PIN_LENGTH) && allDigits(apduBuffer, ISO7816.OFFSET_CDATA, len))) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
}
if (!puk.check(apduBuffer, ISO7816.OFFSET_CDATA, PUK_LENGTH)) {
ISOException.throwIt((short)((short) 0x63c0 | (short) puk.getTriesRemaining()));
}
pin.resetAndUnblock();
pin.update(apduBuffer, (short)(ISO7816.OFFSET_CDATA + PUK_LENGTH), PIN_LENGTH);
pin.check(apduBuffer, (short)(ISO7816.OFFSET_CDATA + PUK_LENGTH), PIN_LENGTH);
puk.reset();
}
private void loadKey(APDU apdu) {

View File

@ -40,4 +40,9 @@ public class WalletAppletCommandSet {
CommandAPDU changePIN = new CommandAPDU(0x80, WalletApplet.INS_CHANGE_PIN, 0, 0, secureChannel.encryptAPDU(pin.getBytes()));
return apduChannel.transmit(changePIN);
}
public ResponseAPDU unblockPIN(String puk, String newPin) throws CardException {
CommandAPDU unblockPIN = new CommandAPDU(0x80, WalletApplet.INS_UNBLOCK_PIN, 0, 0, secureChannel.encryptAPDU((puk + newPin).getBytes()));
return apduChannel.transmit(unblockPIN);
}
}

View File

@ -93,7 +93,8 @@ public class WalletAppletTest {
response = cmdSet.verifyPIN("000000");
assertEquals(0x63C0, response.getSW());
//TODO: Unblock PIN to make the test non-destructive
response = cmdSet.unblockPIN("123456789012", "000000");
assertEquals(0x9000, response.getSW());
}
@Test
@ -135,4 +136,47 @@ public class WalletAppletTest {
response = cmdSet.changePIN("000000");
assertEquals(0x9000, response.getSW());
}
@Test
@DisplayName("UNBLOCK PIN command")
void unblockPinTest() throws CardException {
ResponseAPDU response = cmdSet.changePIN("123456");
assertEquals(0x6985, response.getSW());
cmdSet.openSecureChannel();
response = cmdSet.unblockPIN("123456789012", "000000");
assertEquals(0x6985, response.getSW());
response = cmdSet.verifyPIN("123456");
assertEquals(0x63C2, response.getSW());
response = cmdSet.verifyPIN("123456");
assertEquals(0x63C1, response.getSW());
response = cmdSet.verifyPIN("123456");
assertEquals(0x63C0, response.getSW());
response = cmdSet.unblockPIN("12345678901", "000000");
assertEquals(0x6A80, response.getSW());
response = cmdSet.unblockPIN("1234567890123", "000000");
assertEquals(0x6A80, response.getSW());
response = cmdSet.unblockPIN("123456789010", "000000");
assertEquals(0x63C4, response.getSW());
response = cmdSet.unblockPIN("123456789012", "654321");
assertEquals(0x9000, response.getSW());
apduChannel.getCard().getATR();
cmdSet.select();
cmdSet.openSecureChannel();
response = cmdSet.verifyPIN("654321");
assertEquals(0x9000, response.getSW());
response = cmdSet.changePIN("000000");
assertEquals(0x9000, response.getSW());
}
}