Skip to content
This repository was archived by the owner on May 24, 2026. It is now read-only.
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
Original file line numberDiff line numberDiff line change
Expand Up@@ -221,12 +221,12 @@ public KMAndroidSEProvider() {
// Re-usable AES,DES and HMAC keys in persisted memory.
aesKeys = new AESKey[2];
aesKeys[KEYSIZE_128_OFFSET] = (AESKey) KeyBuilder.buildKey(
KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_128, false);
KeyBuilder.TYPE_AES_TRANSIENT_RESET, KeyBuilder.LENGTH_AES_128, false);
aesKeys[KEYSIZE_256_OFFSET] = (AESKey) KeyBuilder.buildKey(
KeyBuilder.TYPE_AES, KeyBuilder.LENGTH_AES_256, false);
triDesKey = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES,
KeyBuilder.TYPE_AES_TRANSIENT_RESET, KeyBuilder.LENGTH_AES_256, false);
triDesKey = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES_TRANSIENT_RESET,
KeyBuilder.LENGTH_DES3_3KEY, false);
hmacKey = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC, (short) 512,
hmacKey = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC_TRANSIENT_RESET, (short) 512,
false);
rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048);
ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,4 +26,7 @@ public class KMConfigurations {
public static final short CERT_ISSUER_MAX_SIZE = 250;
public static final short CERT_EXPIRY_MAX_SIZE = 20;
public static final short TOTAL_ATTEST_IDS_SIZE = 300;
// If the size of the attestation ids is known and lesser than 64
// then reduce the size here. It reduces the heap memory usage.
public static final byte MAX_ATTESTATION_IDS_SIZE = 64;
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,4 +26,7 @@ public class KMConfigurations {
public static final short CERT_ISSUER_MAX_SIZE = 250;
public static final short CERT_EXPIRY_MAX_SIZE = 20;
public static final short TOTAL_ATTEST_IDS_SIZE = 300;
// If the size of the attestation ids is known and lesser than 64
// then reduce the size here. It reduces the heap memory usage.
public static final byte MAX_ATTESTATION_IDS_SIZE = 64;
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -1340,20 +1340,22 @@ public void testEcImportKeySuccess() {
}

private short extractKeyBlobArray(byte[] buf, short off, short buflen) {
short ret = KMArray.instance((short) 5);
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_SECRET, KMByteBlob.exp());
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_AUTH_TAG, KMByteBlob.exp());
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_NONCE, KMByteBlob.exp());
short ptr = KMKeyCharacteristics.exp();
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_KEYCHAR, ptr);
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_PUB_KEY, KMByteBlob.exp());
short byteBlobExp = KMByteBlob.exp();
short keyChar = KMKeyCharacteristics.exp();
short keyParam = KMKeyParameters.exp();
short ret = KMArray.instance(KMKeymasterApplet.ASYM_KEY_BLOB_SIZE_V1);
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_VERSION_OFFSET, KMInteger.exp());// Version
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_SECRET, byteBlobExp);// Secret
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_NONCE, byteBlobExp);// Nonce
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_AUTH_TAG, byteBlobExp);// AuthTag
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_KEYCHAR, keyChar);// KeyChars
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_CUSTOM_TAGS, keyParam);// KeyChars
KMArray.cast(ret).add(KMKeymasterApplet.KEY_BLOB_PUB_KEY, byteBlobExp);// PubKey

ret =
decoder.decodeArray(
ret,
buf, off, buflen);
short len = KMArray.cast(ret).length();
ptr = KMArray.cast(ret).get((short) 4);
// print(KMByteBlob.cast(ptr).getBuffer(),KMByteBlob.cast(ptr).getStartOff(),KMByteBlob.cast(ptr).length());
return ret;
}

Expand DownExpand Up@@ -2467,7 +2469,7 @@ public void testWithRsa256Oaep() {
@Test
public void testWithRsaSha1Oaep() {
init();
testEncryptDecryptWithRsa(KMType.SHA1, KMType.RSA_OAEP);
testEncryptDecryptWithRsa(KMType.SHA2_256, KMType.RSA_OAEP);
cleanUp();
}

Expand DownExpand Up@@ -2504,7 +2506,7 @@ public short getPublicKey(byte[] keyBlob, short off, short len,
byte[] pubKey, short pubKeyOff) {
short keyBlobPtr = extractKeyBlobArray(keyBlob, off, len);
short arrayLen = KMArray.cast(keyBlobPtr).length();
if (arrayLen < 5) {
if (arrayLen < KMKeymasterApplet.ASYM_KEY_BLOB_SIZE_V1) {
return 0;
}
short pubKeyPtr = KMArray.cast(keyBlobPtr).get(
Expand DownExpand Up@@ -2879,7 +2881,8 @@ public void testVtsRsaPkcs1Success() {

// PKCS1 v1.5 randomizes padding so every result should be different.
Assert.assertFalse(Arrays.equals(cipherText1, cipherText2));

//Clean the heap.
KMRepository.instance().clean();
pkcs1Params = getRsaParams(KMType.DIGEST_NONE,
KMType.RSA_PKCS1_1_5_ENCRYPT);
byte[] plainText = DecryptMessage(cipherText1, pkcs1Params, keyBlob);
Expand Down
82 changes: 44 additions & 38 deletions Applet/src/com/android/javacard/keymaster/KMByteTag.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,29 +30,6 @@ public class KMByteTag extends KMTag {

private static KMByteTag prototype;

// The allowed tag keys of type bool tag
private static final short[] tags = {
APPLICATION_ID,
APPLICATION_DATA,
ROOT_OF_TRUST,
UNIQUE_ID,
ATTESTATION_CHALLENGE,
ATTESTATION_APPLICATION_ID,
ATTESTATION_ID_BRAND,
ATTESTATION_ID_DEVICE,
ATTESTATION_ID_PRODUCT,
ATTESTATION_ID_SERIAL,
ATTESTATION_ID_IMEI,
ATTESTATION_ID_MEID,
ATTESTATION_ID_MANUFACTURER,
ATTESTATION_ID_MODEL,
ASSOCIATED_DATA,
NONCE,
CONFIRMATION_TOKEN,
VERIFIED_BOOT_KEY,
VERIFIED_BOOT_HASH
};

private KMByteTag() {
}

Expand All@@ -74,15 +51,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 DownExpand Up@@ -122,13 +92,49 @@ public short length() {
return KMByteBlob.cast(blobPtr).length();
}

private static boolean validateKey(short key) {
short index = (short) tags.length;
while (--index >= 0) {
if (tags[index] == key) {
return true;
}
private static boolean validateKey(short key, short byteBlob) {
short valueLen = KMByteBlob.cast(byteBlob).length();
switch (key) {
case APPLICATION_ID:
case APPLICATION_DATA:
if (valueLen > MAX_APP_ID_APP_DATA_SIZE) {
KMException.throwIt(KMError.INVALID_INPUT_LENGTH);
}
break;
case ROOT_OF_TRUST:
case UNIQUE_ID:
break;
case ATTESTATION_CHALLENGE:
if (valueLen > MAX_ATTESTATION_CHALLENGE_SIZE) {
KMException.throwIt(KMError.INVALID_INPUT_LENGTH);
}
break;
case ATTESTATION_APPLICATION_ID:
if (valueLen > MAX_ATTESTATION_APP_ID_SIZE) {
KMException.throwIt(KMError.INVALID_INPUT_LENGTH);
}
break;
case ATTESTATION_ID_BRAND:
case ATTESTATION_ID_DEVICE:
case ATTESTATION_ID_PRODUCT:
case ATTESTATION_ID_SERIAL:
case ATTESTATION_ID_IMEI:
case ATTESTATION_ID_MEID:
case ATTESTATION_ID_MANUFACTURER:
case ATTESTATION_ID_MODEL:
if (valueLen > KMConfigurations.MAX_ATTESTATION_IDS_SIZE) {
KMException.throwIt(KMError.INVALID_INPUT_LENGTH);
}
break;
case ASSOCIATED_DATA:
case NONCE:
case CONFIRMATION_TOKEN:
case VERIFIED_BOOT_KEY:
case VERIFIED_BOOT_HASH:
break;
default:
return false;
}
return false;
return true;
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -933,6 +933,9 @@ private void saveAttId() {
tmpVariables[0] = KMKeyParameters.findTag(KMType.BYTES_TAG, attTag, data[KEY_PARAMETERS]);
if (tmpVariables[0] != KMType.INVALID_VALUE) {
tmpVariables[0] = KMByteTag.cast(tmpVariables[0]).getValue();
if (KMByteBlob.cast(tmpVariables[0]).length() > KMConfigurations.MAX_ATTESTATION_IDS_SIZE) {
KMException.throwIt(KMError.INVALID_INPUT_LENGTH);
}
repository.persistAttId(
mapToAttId(attTag),
KMByteBlob.cast(tmpVariables[0]).getBuffer(),
Expand DownExpand Up@@ -987,6 +990,10 @@ private void processGetKeyCharacteristicsCmd(APDU apdu) {
data[APP_ID] = KMArray.cast(tmpVariables[0]).get((short) 1);
data[APP_DATA] = KMArray.cast(tmpVariables[0]).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) {
KMException.throwIt(KMError.INVALID_INPUT_LENGTH);
}
if (!KMByteBlob.cast(data[APP_ID]).isValid()) {
data[APP_ID] = KMType.INVALID_VALUE;
}
Expand Down
8 changes: 8 additions & 0 deletions Applet/src/com/android/javacard/keymaster/KMType.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -296,6 +296,14 @@ public abstract class KMType {
public static final byte KM_KEY_PARAMETERS_OFFSET = KM_TYPE_BASE_OFFSET + 13;
public static final byte KM_VERIFICATION_TOKEN_OFFSET = KM_TYPE_BASE_OFFSET + 14;

// MAX ApplicationID or Application Data size
public static final short MAX_APP_ID_APP_DATA_SIZE = 64;
// Max attestation challenge size.
public static final short MAX_ATTESTATION_CHALLENGE_SIZE = 128;

// Attestation Application ID
public static final short MAX_ATTESTATION_APP_ID_SIZE = 1024;

protected static KMRepository repository;
protected static byte[] heap;
// Instance table
Expand Down