implement GET DATA + STORE DATA
This commit is contained in:
parent
add5da6ce8
commit
7edee9c594
|
@ -25,6 +25,8 @@ public class KeycardApplet extends Applet {
|
||||||
static final byte INS_SIGN = (byte) 0xC0;
|
static final byte INS_SIGN = (byte) 0xC0;
|
||||||
static final byte INS_SET_PINLESS_PATH = (byte) 0xC1;
|
static final byte INS_SET_PINLESS_PATH = (byte) 0xC1;
|
||||||
static final byte INS_EXPORT_KEY = (byte) 0xC2;
|
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;
|
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 KEY_PATH_MAX_DEPTH = 10;
|
||||||
static final byte PAIRING_MAX_CLIENT_COUNT = 5;
|
static final byte PAIRING_MAX_CLIENT_COUNT = 5;
|
||||||
static final byte UID_LENGTH = 16;
|
static final byte UID_LENGTH = 16;
|
||||||
|
static final byte MAX_DATA_LENGTH = 127;
|
||||||
|
|
||||||
static final short CHAIN_CODE_SIZE = 32;
|
static final short CHAIN_CODE_SIZE = 32;
|
||||||
static final short KEY_UID_LENGTH = 32;
|
static final short KEY_UID_LENGTH = 32;
|
||||||
|
@ -141,6 +144,8 @@ public class KeycardApplet extends Applet {
|
||||||
|
|
||||||
private byte[] derivationOutput;
|
private byte[] derivationOutput;
|
||||||
|
|
||||||
|
private byte[] data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked during applet installation. Creates an instance of this class. The installation parameters are passed in
|
* Invoked during applet installation. Creates an instance of this class. The installation parameters are passed in
|
||||||
* the given buffer.
|
* 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);
|
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]);
|
register(bArray, (short) (bOffset + 1), bArray[bOffset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,6 +290,12 @@ public class KeycardApplet extends Applet {
|
||||||
case INS_EXPORT_KEY:
|
case INS_EXPORT_KEY:
|
||||||
exportKey(apdu);
|
exportKey(apdu);
|
||||||
break;
|
break;
|
||||||
|
case INS_GET_DATA:
|
||||||
|
getData(apdu);
|
||||||
|
break;
|
||||||
|
case INS_STORE_DATA:
|
||||||
|
storeData(apdu);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
|
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
|
||||||
break;
|
break;
|
||||||
|
@ -1434,6 +1447,52 @@ public class KeycardApplet extends Applet {
|
||||||
secureChannel.respond(apdu, len, ISO7816.SW_NO_ERROR);
|
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.
|
* Utility method to verify if all the bytes in the buffer between off (included) and off + len (excluded) are digits.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue