Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions Applet/src/com/android/javacard/keymaster/KMByteTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public class KMByteTag extends KMTag {

private static KMByteTag prototype;

// MAX ApplicationID or Application Data size
public static final short MAX_APP_ID_APP_DATA_SIZE = 64;

// The allowed tag keys of type bool tag
private static final short[] tags = {
APPLICATION_ID,
Expand Down Expand Up @@ -76,15 +79,8 @@ public static short exp() {
return ptr;
}

public static short instance(short key) {
if (!validateKey(key)) {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
return instance(key, KMByteBlob.exp());
}

public static short instance(short key, short byteBlob) {
if (!validateKey(key)) {
if (!validateKey(key, byteBlob)) {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
if (heap[byteBlob] != BYTE_BLOB_TYPE) {
Expand Down Expand Up @@ -124,13 +120,20 @@ public short length() {
return KMByteBlob.cast(blobPtr).length();
}

private static boolean validateKey(short key) {
private static boolean validateKey(short key, short keyBlob) {
boolean result = false;
short index = (short) tags.length;
while (--index >= 0) {
if (tags[index] == key) {
return true;
result = true;
if(key == APPLICATION_ID || key == APPLICATION_DATA) {
if (KMByteBlob.cast(keyBlob).length() > MAX_APP_ID_APP_DATA_SIZE) {
result = false;
}
}
break;
}
}
return false;
return result;
}
}
38 changes: 20 additions & 18 deletions Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe
public static final byte INS_UPDATE_CHALLENGE_CMD = KEYMINT_CMD_APDU_START + 32; //0x40
public static final byte INS_FINISH_SEND_DATA_CMD = KEYMINT_CMD_APDU_START + 33; //0x41
public static final byte INS_GET_RESPONSE_CMD = KEYMINT_CMD_APDU_START + 34; //0x42
private static final byte KEYMINT_CMD_APDU_END = KEYMINT_CMD_APDU_START + 35; //0x43
private static final byte INS_GET_HEAP_PROFILE_DATA = KEYMINT_CMD_APDU_START + 35; //0x43
private static final byte KEYMINT_CMD_APDU_END = KEYMINT_CMD_APDU_START + 36; //0x44

private static final byte INS_END_KM_CMD = 0x7F;

Expand Down Expand Up @@ -472,6 +473,9 @@ public void process(APDU apdu) {
case INS_GET_RKP_HARDWARE_INFO:
rkp.process(apduIns, apdu);
break;
case INS_GET_HEAP_PROFILE_DATA:
processGetHeapProfileData(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
Expand Down Expand Up @@ -585,6 +589,7 @@ protected void resetData() {
*/
public static void sendOutgoing(APDU apdu, short resp) {
//TODO handle the extended buffer stuff. We can reuse this.
short usedHeap = repository.getHeapIndex();
short bufferStartOffset = repository.allocAvailableMemory();
byte[] buffer = repository.getHeap();
// TODO we can change the following to incremental send.
Expand All @@ -593,6 +598,7 @@ public static void sendOutgoing(APDU apdu, short resp) {
.getHeap().length)) {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
repository.updateHeapProfileData((short)(usedHeap + bufferLength));
// Send data
apdu.setOutgoing();
apdu.setOutgoingLength(bufferLength);
Expand Down Expand Up @@ -683,6 +689,10 @@ private void processGetKeyCharacteristicsCmd(APDU apdu) {
data[KEY_BLOB] = KMArray.cast(cmd).get((short) 0);
data[APP_ID] = KMArray.cast(cmd).get((short) 1);
data[APP_DATA] = KMArray.cast(cmd).get((short) 2);
if (KMByteBlob.cast(data[APP_ID]).length() > KMByteTag.MAX_APP_ID_APP_DATA_SIZE
|| KMByteBlob.cast(data[APP_DATA]).length() > KMByteTag.MAX_APP_ID_APP_DATA_SIZE) {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
if (!KMByteBlob.cast(data[APP_ID]).isValid()) {
data[APP_ID] = KMType.INVALID_VALUE;
}
Expand Down Expand Up @@ -744,21 +754,6 @@ private short keyBlob(){
}

private void processDeleteKeyCmd(APDU apdu) {
short cmd = deleteKeyCmd(apdu);
data[KEY_BLOB] = KMArray.cast(cmd).get((short) 0);
try {
data[KEY_BLOB] = decoder.decodeArray(keyBlob(),
KMByteBlob.cast(data[KEY_BLOB]).getBuffer(),
KMByteBlob.cast(data[KEY_BLOB]).getStartOff(),
KMByteBlob.cast(data[KEY_BLOB]).length());
} catch (ISOException e) {
// As per VTS, deleteKey should return KMError.OK but in case if
// input is empty then VTS accepts UNIMPLEMENTED errorCode as well.
KMException.throwIt(KMError.UNIMPLEMENTED);
}
if (KMArray.cast(data[KEY_BLOB]).length() < 4) {
KMException.throwIt(KMError.INVALID_KEY_BLOB);
}
// Send ok
sendError(apdu, KMError.OK);
}
Expand Down Expand Up @@ -1223,7 +1218,6 @@ private KMAttestationCert makeCommonCert(byte[] scratchPad) {
return cert;
}


private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyParam, short attChallenge, short issuer,
short hwParameters, short swParameters, byte[] scratchPad) {
KMAttestationCert cert = makeCommonCert(scratchPad);
Expand Down Expand Up @@ -1294,7 +1288,6 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara
cert.verifiedBootHash(getVerifiedBootHash(scratchPad));
cert.verifiedBootKey(getBootKey(scratchPad));
cert.verifiedBootState((byte) kmDataStore.getBootState());

data[SECRET] = privKey;
data[KEY_BLOB] = origBlob;
return cert;
Expand Down Expand Up @@ -4222,4 +4215,13 @@ private void finishTrustedConfirmationOperation(KMOperationState op) {
}
}
}

private void processGetHeapProfileData(APDU apdu) {
// No Arguments
// prepare the response
short resp = KMArray.instance((short) 2);
KMArray.cast(resp).add((short) 0, KMInteger.uint_16(KMError.OK));
KMArray.cast(resp).add((short) 1, KMInteger.uint_16(repository.getMaxHeapUsed()));
sendOutgoing(apdu, resp);
}
}
17 changes: 17 additions & 0 deletions Applet/src/com/android/javacard/keymaster/KMRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class KMRepository {
private byte[] heap;
private short[] heapIndex;
private short reclaimIndex;
//used for heap profiling
public static short[] maxHeapUsage;

// Singleton instance
private static KMRepository repository;
Expand All @@ -49,6 +51,7 @@ public static KMRepository instance() {
public KMRepository(boolean isUpgrading) {
heap = JCSystem.makeTransientByteArray(HEAP_SIZE, JCSystem.CLEAR_ON_RESET);
heapIndex = JCSystem.makeTransientShortArray((short)1, JCSystem.CLEAR_ON_RESET);
maxHeapUsage = JCSystem.makeTransientShortArray((short)1, JCSystem.CLEAR_ON_RESET);
reclaimIndex = HEAP_SIZE;
repository = this;
}
Expand Down Expand Up @@ -114,5 +117,19 @@ public short alloc(short length) {
public byte[] getHeap() {
return heap;
}

public short getHeapIndex() {
return heapIndex[0];
}

public void updateHeapProfileData(short size) {
if(size > maxHeapUsage[0]) {
maxHeapUsage[0] = size;
}
}

public short getMaxHeapUsed() {
return maxHeapUsage[0];
}

}
8 changes: 7 additions & 1 deletion HAL/JavacardKeyMintOperation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,21 @@ ScopedAStatus JavacardKeyMintOperation::finish(
const vector<uint8_t> inData = input.value_or(vector<uint8_t>());
DataView view = {.buffer = {}, .data = inData, .start = 0, .length = inData.size()};
const vector<uint8_t> sign = signature.value_or(vector<uint8_t>());
appendBufferedData(view);
if (!(bufferingMode_ == BufferingMode::EC_NO_DIGEST ||
bufferingMode_ == BufferingMode::RSA_NO_DIGEST)) {
appendBufferedData(view);
if (view.length > MAX_CHUNK_SIZE) {
auto err = updateInChunks(view, aToken, tToken, output);
if (err != KM_ERROR_OK) {
return km_utils::kmError2ScopedAStatus(err);
}
}
} else {
keymaster_error_t err = bufferData(view);
if (err != KM_ERROR_OK) {
return km_utils::kmError2ScopedAStatus(err);
}
appendBufferedData(view);
}
vector<uint8_t> remaining = popNextChunk(view, view.length);
return km_utils::kmError2ScopedAStatus(sendFinish(remaining, sign, aToken, tToken, confToken, *output));
Expand Down