diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java index 4c283770..54576b59 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEProvider.java @@ -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); diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMConfigurations.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMConfigurations.java index 6e5090a1..1b09fa53 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMConfigurations.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMConfigurations.java @@ -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; } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMConfigurations.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMConfigurations.java index 6e5090a1..1b09fa53 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMConfigurations.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMConfigurations.java @@ -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; } diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index 42f102e9..accdbbcd 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -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; } @@ -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(); } @@ -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( @@ -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); diff --git a/Applet/src/com/android/javacard/keymaster/KMByteTag.java b/Applet/src/com/android/javacard/keymaster/KMByteTag.java index 89401e4f..c37fd8fc 100644 --- a/Applet/src/com/android/javacard/keymaster/KMByteTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMByteTag.java @@ -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() { } @@ -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) { @@ -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; } } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index f7dd2ca5..ae378924 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -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(), @@ -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; } diff --git a/Applet/src/com/android/javacard/keymaster/KMType.java b/Applet/src/com/android/javacard/keymaster/KMType.java index 00704df2..f787c4b0 100644 --- a/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/Applet/src/com/android/javacard/keymaster/KMType.java @@ -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