Skip to content

Commit

Permalink
implement factory reset
Browse files Browse the repository at this point in the history
  • Loading branch information
bitgamma committed Jun 6, 2023
1 parent 4a04bda commit 039964e
Showing 1 changed file with 42 additions and 10 deletions.
52 changes: 42 additions & 10 deletions src/main/java/im/status/keycard/KeycardApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -282,6 +286,9 @@ public void process(APDU apdu) throws ISOException {
case INS_STORE_DATA:
storeData(apdu);
break;
case INS_FACTORY_RESET:
factoryReset(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
break;
Expand Down Expand Up @@ -1008,6 +1015,23 @@ private short logicrShift(short v, short amount) {
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.
Expand All @@ -1022,16 +1046,24 @@ private void removeKey(APDU apdu) {
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();
}

/**
Expand Down

0 comments on commit 039964e

Please sign in to comment.