implement GET DATA + STORE DATA

This commit is contained in:
Michele Balistreri 2019-04-09 10:40:47 +03:00
parent add5da6ce8
commit 7edee9c594
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
1 changed files with 59 additions and 0 deletions

View File

@ -25,6 +25,8 @@ public class KeycardApplet extends Applet {
static final byte INS_SIGN = (byte) 0xC0;
static final byte INS_SET_PINLESS_PATH = (byte) 0xC1;
static final byte INS_EXPORT_KEY = (byte) 0xC2;
static final byte INS_GET_DATA = (byte) 0xCA;
static final byte INS_STORE_DATA = (byte) 0xE2;
static final short SW_REFERENCED_DATA_NOT_FOUND = (short) 0x6A88;
@ -35,6 +37,7 @@ public class KeycardApplet extends Applet {
static final byte KEY_PATH_MAX_DEPTH = 10;
static final byte PAIRING_MAX_CLIENT_COUNT = 5;
static final byte UID_LENGTH = 16;
static final byte MAX_DATA_LENGTH = 127;
static final short CHAIN_CODE_SIZE = 32;
static final short KEY_UID_LENGTH = 32;
@ -141,6 +144,8 @@ public class KeycardApplet extends Applet {
private byte[] derivationOutput;
private byte[] data;
/**
* Invoked during applet installation. Creates an instance of this class. The installation parameters are passed in
* the given buffer.
@ -201,6 +206,8 @@ public class KeycardApplet extends Applet {
derivationOutput = JCSystem.makeTransientByteArray((short) (Crypto.KEY_SECRET_SIZE + CHAIN_CODE_SIZE), JCSystem.CLEAR_ON_RESET);
data = new byte[MAX_DATA_LENGTH + 1];
register(bArray, (short) (bOffset + 1), bArray[bOffset]);
}
@ -283,6 +290,12 @@ public class KeycardApplet extends Applet {
case INS_EXPORT_KEY:
exportKey(apdu);
break;
case INS_GET_DATA:
getData(apdu);
break;
case INS_STORE_DATA:
storeData(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
break;
@ -1434,6 +1447,52 @@ public class KeycardApplet extends Applet {
secureChannel.respond(apdu, len, ISO7816.SW_NO_ERROR);
}
/**
* Processes the GET DATA command.
*
* @param apdu the JCRE-owned APDU object.
*/
private void getData(APDU apdu) {
byte[] apduBuffer = apdu.getBuffer();
if (secureChannel.isOpen()) {
secureChannel.preprocessAPDU(apduBuffer);
}
short outLen = Util.makeShort((byte) 0x00, data[0]);
Util.arrayCopyNonAtomic(data, (short) 1, apduBuffer, SecureChannel.SC_OUT_OFFSET, outLen);
if (secureChannel.isOpen()) {
secureChannel.respond(apdu, outLen, ISO7816.SW_NO_ERROR);
} else {
apdu.setOutgoingAndSend(SecureChannel.SC_OUT_OFFSET, outLen);
}
}
/**
* Processes the STORE DATA command. Requires an open secure channel and the PIN to be verified.
*
* @param apdu the JCRE-owned APDU object.
*/
private void storeData(APDU apdu) {
byte[] apduBuffer = apdu.getBuffer();
secureChannel.preprocessAPDU(apduBuffer);
if (!pin.isValidated()) {
ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED);
}
short dataLen = Util.makeShort((byte) 0x00, apduBuffer[ISO7816.OFFSET_LC]);
if (dataLen > MAX_DATA_LENGTH) {
ISOException.throwIt(ISO7816.SW_WRONG_DATA);
}
JCSystem.beginTransaction();
Util.arrayCopy(apduBuffer, ISO7816.OFFSET_LC, data, (short) 0, (short)(dataLen + 1));
JCSystem.commitTransaction();
}
/**
* Utility method to verify if all the bytes in the buffer between off (included) and off + len (excluded) are digits.
*