From 039964e8d0e5bc62c709a70f41cbe013a3114515 Mon Sep 17 00:00:00 2001 From: Michele Balistreri Date: Tue, 6 Jun 2023 10:46:46 +0200 Subject: [PATCH] implement factory reset --- .../java/im/status/keycard/KeycardApplet.java | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/main/java/im/status/keycard/KeycardApplet.java b/src/main/java/im/status/keycard/KeycardApplet.java index aee521e..f3db6a5 100644 --- a/src/main/java/im/status/keycard/KeycardApplet.java +++ b/src/main/java/im/status/keycard/KeycardApplet.java @@ -13,6 +13,7 @@ public class KeycardApplet extends Applet { static final byte INS_GET_STATUS = (byte) 0xF2; static final byte INS_INIT = (byte) 0xFE; + static final byte INS_FACTORY_RESET = (byte) 0xFD; static final byte INS_VERIFY_PIN = (byte) 0x20; static final byte INS_CHANGE_PIN = (byte) 0x21; static final byte INS_UNBLOCK_PIN = (byte) 0x22; @@ -85,6 +86,9 @@ public class KeycardApplet extends Applet { static final byte STORE_DATA_P1_NDEF = 0x01; static final byte STORE_DATA_P1_CASH = 0x02; + static final byte FACTORY_RESET_P1_MAGIC = (byte) 0xAA; + static final byte FACTORY_RESET_P2_MAGIC = 0x55; + static final byte TLV_SIGNATURE_TEMPLATE = (byte) 0xA0; static final byte TLV_KEY_TEMPLATE = (byte) 0xA1; @@ -282,6 +286,9 @@ public class KeycardApplet extends Applet { case INS_STORE_DATA: storeData(apdu); break; + case INS_FACTORY_RESET: + factoryReset(apdu); + break; default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); break; @@ -1008,6 +1015,23 @@ public class KeycardApplet extends Applet { return (short) ((short)((short) 0x4000 >>> (short) (amount - 1)) | tmp); } + /** + * Clear all keys and erases the key UID. + */ + private void clearKeys() { + keyPathLen = 0; + pinlessPathLen = 0; + isExtended = false; + masterPrivate.clearKey(); + masterPublic.clearKey(); + resetCurveParameters(); + Util.arrayFillNonAtomic(masterChainCode, (short) 0, (short) masterChainCode.length, (byte) 0); + Util.arrayFillNonAtomic(altChainCode, (short) 0, (short) altChainCode.length, (byte) 0); + Util.arrayFillNonAtomic(keyPath, (short) 0, (short) keyPath.length, (byte) 0); + Util.arrayFillNonAtomic(pinlessPath, (short) 0, (short) pinlessPath.length, (byte) 0); + Util.arrayFillNonAtomic(keyUID, (short) 0, (short) keyUID.length, (byte) 0); + } + /** * Processes the REMOVE KEY command. Removes the master key and all derived keys. Secure Channel and PIN * authentication are required. @@ -1022,16 +1046,24 @@ public class KeycardApplet extends Applet { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } - keyPathLen = 0; - pinlessPathLen = 0; - isExtended = false; - masterPrivate.clearKey(); - masterPublic.clearKey(); - resetCurveParameters(); - Util.arrayFillNonAtomic(masterChainCode, (short) 0, (short) masterChainCode.length, (byte) 0); - Util.arrayFillNonAtomic(altChainCode, (short) 0, (short) altChainCode.length, (byte) 0); - Util.arrayFillNonAtomic(keyPath, (short) 0, (short) keyPath.length, (byte) 0); - Util.arrayFillNonAtomic(pinlessPath, (short) 0, (short) pinlessPath.length, (byte) 0); + clearKeys(); + } + + private void factoryReset(APDU apdu) { + byte[] apduBuffer = apdu.getBuffer(); + + if ((apduBuffer[OFFSET_P1] != FACTORY_RESET_P1_MAGIC) || (apduBuffer[OFFSET_P2] != FACTORY_RESET_P2_MAGIC)) { + ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2); + } + + clearKeys(); + pin = null; + altPIN = null; + puk = null; + secureChannel = null; + crypto.random.generateData(uid, (short) 0, UID_LENGTH); + Util.arrayFillNonAtomic(data, (short) 0, (short) data.length, (byte) 0); + JCSystem.requestObjectDeletion(); } /**