add optional PIN/PUK retry count in INIT

This commit is contained in:
Michele Balistreri 2020-02-13 14:51:31 +03:00
parent f420fd962f
commit 6a40687804
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
2 changed files with 31 additions and 8 deletions

View File

@ -31,7 +31,7 @@ javacard {
aid = '0xA0:0x00:0x00:0x08:0x04:0x00:0x01:0x03'
className = 'CashApplet'
}
version = '3.0'
version = '3.1'
}
}

View File

@ -2,7 +2,6 @@ package im.status.keycard;
import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.Cipher;
import static javacard.framework.ISO7816.OFFSET_P1;
@ -30,10 +29,15 @@ public class KeycardApplet extends Applet {
static final short SW_REFERENCED_DATA_NOT_FOUND = (short) 0x6A88;
static final byte PIN_MIN_RETRIES = 2;
static final byte PIN_MAX_RETRIES = 10;
static final byte PUK_MIN_RETRIES = 3;
static final byte PUK_MAX_RETRIES = 12;
static final byte PUK_LENGTH = 12;
static final byte PUK_MAX_RETRIES = 5;
static final byte DEFAULT_PUK_MAX_RETRIES = 5;
static final byte PIN_LENGTH = 6;
static final byte PIN_MAX_RETRIES = 3;
static final byte DEFAULT_PIN_MAX_RETRIES = 3;
static final byte KEY_PATH_MAX_DEPTH = 10;
static final byte PAIRING_MAX_CLIENT_COUNT = 5;
static final byte UID_LENGTH = 16;
@ -326,17 +330,36 @@ public class KeycardApplet extends Applet {
} else if (apduBuffer[ISO7816.OFFSET_INS] == INS_INIT) {
secureChannel.oneShotDecrypt(apduBuffer);
if ((apduBuffer[ISO7816.OFFSET_LC] != (byte)(PIN_LENGTH + PUK_LENGTH + SecureChannel.SC_SECRET_LENGTH)) || !allDigits(apduBuffer, ISO7816.OFFSET_CDATA, (short)(PIN_LENGTH + PUK_LENGTH))) {
byte defaultLimitsLen = (byte)(PIN_LENGTH + PUK_LENGTH + SecureChannel.SC_SECRET_LENGTH);
byte withLimitsLen = (byte) (defaultLimitsLen + 2);
if (((apduBuffer[ISO7816.OFFSET_LC] != defaultLimitsLen) && (apduBuffer[ISO7816.OFFSET_LC] != withLimitsLen)) || !allDigits(apduBuffer, ISO7816.OFFSET_CDATA, (short)(PIN_LENGTH + PUK_LENGTH))) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
}
JCSystem.beginTransaction();
byte pinLimit;
byte pukLimit;
if (apduBuffer[ISO7816.OFFSET_LC] == withLimitsLen) {
pinLimit = apduBuffer[(short) (ISO7816.OFFSET_CDATA + defaultLimitsLen)];
pukLimit = apduBuffer[(short) (ISO7816.OFFSET_CDATA + defaultLimitsLen + 1)];
if (pinLimit < PIN_MIN_RETRIES || pinLimit > PIN_MAX_RETRIES || pukLimit < PUK_MIN_RETRIES || pukLimit > PUK_MAX_RETRIES) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
}
} else {
pinLimit = DEFAULT_PIN_MAX_RETRIES;
pukLimit = DEFAULT_PUK_MAX_RETRIES;
}
secureChannel.initSecureChannel(apduBuffer, (short)(ISO7816.OFFSET_CDATA + PIN_LENGTH + PUK_LENGTH));
pin = new OwnerPIN(PIN_MAX_RETRIES, PIN_LENGTH);
JCSystem.beginTransaction();
pin = new OwnerPIN(pinLimit, PIN_LENGTH);
pin.update(apduBuffer, ISO7816.OFFSET_CDATA, PIN_LENGTH);
puk = new OwnerPIN(PUK_MAX_RETRIES, PUK_LENGTH);
puk = new OwnerPIN(pukLimit, PUK_LENGTH);
puk.update(apduBuffer, (short)(ISO7816.OFFSET_CDATA + PIN_LENGTH), PUK_LENGTH);
JCSystem.commitTransaction();