From 91b4a96194b3f68767f22e33a4a79447c958ef32 Mon Sep 17 00:00:00 2001 From: Michele Balistreri Date: Wed, 27 Sep 2017 19:49:02 +0300 Subject: [PATCH] implement UNBLOCK PIN --- .../java/im/status/wallet/WalletApplet.java | 23 ++++++++-- .../status/wallet/WalletAppletCommandSet.java | 5 ++ .../im/status/wallet/WalletAppletTest.java | 46 ++++++++++++++++++- 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/main/java/im/status/wallet/WalletApplet.java b/src/main/java/im/status/wallet/WalletApplet.java index f586221..a8307b3 100644 --- a/src/main/java/im/status/wallet/WalletApplet.java +++ b/src/main/java/im/status/wallet/WalletApplet.java @@ -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) { diff --git a/src/test/java/im/status/wallet/WalletAppletCommandSet.java b/src/test/java/im/status/wallet/WalletAppletCommandSet.java index 877692c..83a84d4 100644 --- a/src/test/java/im/status/wallet/WalletAppletCommandSet.java +++ b/src/test/java/im/status/wallet/WalletAppletCommandSet.java @@ -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); + } } diff --git a/src/test/java/im/status/wallet/WalletAppletTest.java b/src/test/java/im/status/wallet/WalletAppletTest.java index 76b2f4d..cc9808c 100644 --- a/src/test/java/im/status/wallet/WalletAppletTest.java +++ b/src/test/java/im/status/wallet/WalletAppletTest.java @@ -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()); + } }