From 4a94910635fc991bd1de4e3d44ff2ebe437c0b3e Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Fri, 13 May 2022 03:34:02 +0000 Subject: [PATCH 1/3] ByteTag length validations Use Transient key objects --- .../keymaster/KMAndroidSEProvider.java | 8 +- .../javacard/keymaster/KMConfigurations.java | 3 + .../javacard/keymaster/KMConfigurations.java | 3 + .../javacard/test/KMFunctionalTest.java | 29 ++++--- .../android/javacard/keymaster/KMByteTag.java | 82 ++++++++++--------- .../javacard/keymaster/KMKeymasterApplet.java | 8 ++ .../android/javacard/keymaster/KMType.java | 8 ++ 7 files changed, 86 insertions(+), 55 deletions(-) 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 5a2a6f82..c171400c 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -932,6 +932,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(), @@ -985,6 +988,11 @@ private void processGetKeyCharacteristicsCmd(APDU apdu) { data[KEY_BLOB] = KMArray.cast(tmpVariables[0]).get((short) 0); 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 From 8b65cc01d7381ef3ddb4e5b82f513ddcc6daad8a Mon Sep 17 00:00:00 2001 From: "avinash.hedage" Date: Fri, 13 May 2022 04:27:47 +0000 Subject: [PATCH 2/3] Updated aosp integration patches --- .../device_google_cuttlefish.patch | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/aosp_integration_patches/device_google_cuttlefish.patch b/aosp_integration_patches/device_google_cuttlefish.patch index 750eb6ff..6ae4f23d 100644 --- a/aosp_integration_patches/device_google_cuttlefish.patch +++ b/aosp_integration_patches/device_google_cuttlefish.patch @@ -1,8 +1,8 @@ diff --git a/shared/device.mk b/shared/device.mk -index c0b6112c7..6d9362ea4 100644 +index c9221ec36..eeae0a965 100644 --- a/shared/device.mk +++ b/shared/device.mk -@@ -576,6 +576,9 @@ endif +@@ -621,6 +621,9 @@ endif PRODUCT_PACKAGES += \ $(LOCAL_KEYMINT_PRODUCT_PACKAGE) @@ -13,11 +13,11 @@ index c0b6112c7..6d9362ea4 100644 ifneq ($(LOCAL_PREFER_VENDOR_APEX),true) PRODUCT_COPY_FILES += \ diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts -index 55b8d964e..80732eb7b 100644 +index 6c471b8b8..5baf83c4c 100644 --- a/shared/sepolicy/vendor/file_contexts +++ b/shared/sepolicy/vendor/file_contexts -@@ -86,6 +86,7 @@ - /vendor/bin/hw/android\.hardware\.thermal@2\.0-service\.mock u:object_r:hal_thermal_default_exec:s0 +@@ -94,6 +94,7 @@ + /vendor/bin/hw/android\.hardware\.identity-service\.remote u:object_r:hal_identity_remote_exec:s0 /vendor/bin/hw/android\.hardware\.security\.keymint-service\.remote u:object_r:hal_keymint_remote_exec:s0 /vendor/bin/hw/android\.hardware\.keymaster@4\.1-service.remote u:object_r:hal_keymaster_remote_exec:s0 +/vendor/bin/hw/android\.hardware\.keymaster@4\.1-strongbox\.service u:object_r:hal_keymaster_strongbox_exec:s0 @@ -44,15 +44,3 @@ index 000000000..40cb82c3f +allow hal_keymaster_strongbox port_type:tcp_socket name_connect; +allow hal_keymaster_strongbox port:tcp_socket { name_connect }; +allow hal_keymaster_strongbox vendor_data_file:file { open read getattr }; -diff --git a/shared/sepolicy/vendor/service_contexts b/shared/sepolicy/vendor/service_contexts -index d20d026cf..214576e3e 100644 ---- a/shared/sepolicy/vendor/service_contexts -+++ b/shared/sepolicy/vendor/service_contexts -@@ -4,6 +4,7 @@ android.hardware.neuralnetworks.IDevice/nnapi-sample_float_slow u:object_r:hal_n - android.hardware.neuralnetworks.IDevice/nnapi-sample_minimal u:object_r:hal_neuralnetworks_service:s0 - android.hardware.neuralnetworks.IDevice/nnapi-sample_quant u:object_r:hal_neuralnetworks_service:s0 - android.hardware.neuralnetworks.IDevice/nnapi-sample_sl_shim u:object_r:hal_neuralnetworks_service:s0 -+android.hardware.keymaster@4.1::IKeymasterDevice/strongbox u:object_r:hal_keymaster_service:s0 - - # Binder service mappings - gce u:object_r:gce_service:s0 From 579b852b5a55d5c69f3345fffe8b3c7561ea6247 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Fri, 13 May 2022 01:20:03 +0000 Subject: [PATCH 3/3] Critical bug fixes ported from Keymint --- .../javacard/keymaster/KMAndroidSEApplet.java | 2 +- .../keymaster/KMAttestationCertImpl.java | 11 +-- .../javacard/keymaster/KMRsaOAEPEncoding.java | 4 +- .../android/javacard/keymaster/KMUtils.java | 13 ++- .../keymaster/KMAttestationCertImpl.java | 11 +-- .../android/javacard/keymaster/KMUtils.java | 15 ++-- .../android/javacard/keymaster/KMArray.java | 5 ++ .../android/javacard/keymaster/KMDecoder.java | 4 +- .../javacard/keymaster/KMKeyParameters.java | 2 - .../javacard/keymaster/KMKeymasterApplet.java | 83 ++++++++++--------- .../javacard/keymaster/KMRepository.java | 1 + .../4.1/JavacardKeymaster4Device.cpp | 2 +- 12 files changed, 80 insertions(+), 73 deletions(-) diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java index befab92f..3dc1aabf 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java @@ -115,7 +115,7 @@ public boolean isUpgradeAllowed(short version) { upgradeAllowed = true; } } else if ((short) (currentMajorVersion - oldMajorVersion) == 0) { - if ((short) (currentMinorVersion - oldMinorVersion) == 1) { + if (currentMinorVersion >= oldMinorVersion) { upgradeAllowed = true; } } diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 7e5eb5cc..5ff8cc63 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -78,7 +78,8 @@ public class KMAttestationCertImpl implements KMAttestationCert { KMType.USAGE_EXPIRE_DATETIME, KMType.ORIGINATION_EXPIRE_DATETIME, KMType.ACTIVE_DATETIME, - KMType.UNLOCKED_DEVICE_REQUIRED + KMType.UNLOCKED_DEVICE_REQUIRED, + KMType.ALLOW_WHILE_ON_BODY }; // Below are the allowed hardwareEnforced Authorization tags inside the attestation certificate's extension. @@ -89,8 +90,8 @@ public class KMAttestationCertImpl implements KMAttestationCert { KMType.ATTESTATION_ID_SERIAL, KMType.ATTESTATION_ID_PRODUCT, KMType.ATTESTATION_ID_DEVICE, KMType.ATTESTATION_ID_BRAND, KMType.OS_PATCH_LEVEL, KMType.OS_VERSION, KMType.ROOT_OF_TRUST, - KMType.ORIGIN, KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, - KMType.NO_AUTH_REQUIRED, KMType.USER_SECURE_ID, + KMType.ORIGIN, KMType.TRUSTED_CONFIRMATION_REQUIRED, KMType.AUTH_TIMEOUT, + KMType.USER_AUTH_TYPE, KMType.NO_AUTH_REQUIRED, KMType.RSA_PUBLIC_EXPONENT, KMType.ECCURVE, KMType.MIN_MAC_LENGTH, KMType.CALLER_NONCE, KMType.PADDING, KMType.DIGEST, KMType.BLOCK_MODE, KMType.KEYSIZE, KMType.ALGORITHM, KMType.PURPOSE}; @@ -227,10 +228,10 @@ public KMAttestationCert notBefore(short obj, byte[] scratchpad) { public KMAttestationCert notAfter(short usageExpiryTimeObj, short certExpirtyTimeObj, byte[] scratchPad, short tmpVar) { if (usageExpiryTimeObj != KMType.INVALID_VALUE) { - // compare if the expiry time is greater then 2051 then use generalized + // compare if the expiry time is greater then 2050 then use generalized // time format else use utc time format. usageExpiryTimeObj = KMIntegerTag.cast(usageExpiryTimeObj).getValue(); - tmpVar = KMInteger.uint_64(KMUtils.firstJan2051, (short) 0); + tmpVar = KMInteger.uint_64(KMUtils.firstJan2050, (short) 0); if (KMInteger.compare(usageExpiryTimeObj, tmpVar) >= 0) { usageExpiryTimeObj = KMUtils.convertToDate(usageExpiryTimeObj, scratchPad, false); diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsaOAEPEncoding.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsaOAEPEncoding.java index ac099bc5..0b6c327b 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsaOAEPEncoding.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMRsaOAEPEncoding.java @@ -69,7 +69,7 @@ private short getDigestLength() { return MessageDigest.LENGTH_SHA_256; case MessageDigest.ALG_SHA_384: return MessageDigest.LENGTH_SHA_384; - case MessageDigest.ALG_SHA3_512: + case MessageDigest.ALG_SHA_512: return MessageDigest.LENGTH_SHA_512; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); @@ -257,4 +257,4 @@ private short rsaOAEPDecode(byte[] encodedMsg, short encodedMsgOff, KMAndroidSEProvider.TMP_ARRAY_SIZE, (byte) 0); } } -} \ No newline at end of file +} diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java index 7be6bce1..b08fe40d 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -39,9 +39,8 @@ public class KMUtils { 0, 0, 0, 0x1D, 0x63, (byte) 0xEB, 0x0C, 0x00};//126230400000 public static final byte[] firstJan2020 = { 0, 0, 0x01, 0x6F, 0x5E, 0x66, (byte) 0xE8, 0x00}; // 1577836800000 msec - public static final byte[] firstJan2051 = { - 0, 0, 0x02, 0x53, 0x26, (byte) 0x0E, (byte) 0x1C, 0x00}; // 2556144000000 - // msec + public static final byte[] firstJan2050 = { + 0, 0, 0x02, 0x4b, (byte) 0xCE, 0x5C, (byte)0xF0, 0x00}; //2524608000000 msec public static final byte[] febMonthLeapMSec = { 0, 0, 0, 0, (byte) 0x95, 0x58, 0x6C, 0x00}; //2505600000 public static final byte[] febMonthMsec = { @@ -78,12 +77,12 @@ public static short convertToDate(short time, byte[] scratchPad, KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2050, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2050, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -92,7 +91,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8); } else { from2020 = false; - Util.arrayCopyNonAtomic(firstJan2051, (short) 0, scratchPad, (short) 8, + Util.arrayCopyNonAtomic(firstJan2050, (short) 0, scratchPad, (short) 8, (short) 8); subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -397,7 +396,7 @@ public static short countTemporalCount(byte[] bufTime, short timeOff, scratchPad, (short) (offset + 8 - timeLen), timeLen); - Util.arrayCopyNonAtomic(oneMonthMsec, (short) 0, scratchPad, (short) (offset + 8), + Util.arrayCopyNonAtomic(ThirtDaysMonthMsec, (short) 0, scratchPad, (short) (offset + 8), (short) 8); return divide(scratchPad, (short) 0, (short) 8, (short) 16); } diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java index 6ca72904..6d75d076 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMAttestationCertImpl.java @@ -196,10 +196,10 @@ public KMAttestationCert notBefore(short obj, byte[] scratchpad) { public KMAttestationCert notAfter(short usageExpiryTimeObj, short certExpirtyTimeObj, byte[] scratchPad, short tmpVar) { if (usageExpiryTimeObj != KMType.INVALID_VALUE) { - // compare if the expiry time is greater then 2051 then use generalized + // compare if the expiry time is greater then 2050 then use generalized // time format else use utc time format. usageExpiryTimeObj = KMIntegerTag.cast(usageExpiryTimeObj).getValue(); - tmpVar = KMInteger.uint_64(KMUtils.firstJan2051, (short) 0); + tmpVar = KMInteger.uint_64(KMUtils.firstJan2050, (short) 0); if (KMInteger.compare(usageExpiryTimeObj, tmpVar) >= 0) { usageExpiryTimeObj = KMUtils.convertToDate(usageExpiryTimeObj, scratchPad, false); @@ -449,7 +449,8 @@ private static void pushSWParams() { short[] tagIds = { KMType.ATTESTATION_APPLICATION_ID, KMType.CREATION_DATETIME, KMType.USAGE_EXPIRE_DATETIME, KMType.ORIGINATION_EXPIRE_DATETIME, - KMType.ACTIVE_DATETIME, KMType.UNLOCKED_DEVICE_REQUIRED}; + KMType.ACTIVE_DATETIME, KMType.UNLOCKED_DEVICE_REQUIRED, + KMType.ALLOW_WHILE_ON_BODY}; byte index = 0; do { pushParams(swParams, swParamsIndex, tagIds[index]); @@ -467,8 +468,8 @@ private static void pushHWParams() { KMType.ATTESTATION_ID_SERIAL, KMType.ATTESTATION_ID_PRODUCT, KMType.ATTESTATION_ID_DEVICE, KMType.ATTESTATION_ID_BRAND, KMType.OS_PATCH_LEVEL, KMType.OS_VERSION, KMType.ROOT_OF_TRUST, - KMType.ORIGIN, KMType.AUTH_TIMEOUT, KMType.USER_AUTH_TYPE, - KMType.NO_AUTH_REQUIRED, KMType.USER_SECURE_ID, + KMType.ORIGIN, KMType.TRUSTED_CONFIRMATION_REQUIRED, KMType.AUTH_TIMEOUT, + KMType.USER_AUTH_TYPE, KMType.NO_AUTH_REQUIRED, KMType.RSA_PUBLIC_EXPONENT, KMType.ECCURVE, KMType.MIN_MAC_LENGTH, KMType.CALLER_NONCE, KMType.PADDING, KMType.DIGEST, KMType.BLOCK_MODE, KMType.KEYSIZE, KMType.ALGORITHM, KMType.PURPOSE}; diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java index a572da17..567b55cd 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMUtils.java @@ -39,9 +39,8 @@ public class KMUtils { 0, 0, 0, 0x1D, 0x63, (byte) 0xEB, 0x0C, 0x00};//126230400000 public static final byte[] firstJan2020 = { 0, 0, 0x01, 0x6F, 0x5E, 0x66, (byte) 0xE8, 0x00}; // 1577836800000 msec - public static final byte[] firstJan2051 = { - 0, 0, 0x02, 0x53, 0x26, (byte) 0x0E, (byte) 0x1C, 0x00}; // 2556144000000 - // msec + public static final byte[] firstJan2050 = { + 0, 0, 0x02, 0x4b, (byte) 0xCE, 0x5C, (byte)0xF0, 0x00}; //2524608000000 msec public static final byte[] febMonthLeapMSec = { 0, 0, 0, 0, (byte) 0x95, 0x58, 0x6C, 0x00}; //2505600000 public static final byte[] febMonthMsec = { @@ -76,12 +75,12 @@ public static short convertToDate(short time, byte[] scratchPad, KMException.throwIt(KMError.INVALID_ARGUMENT); } if (utcFlag - && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, + && KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2050, (short) 0, (short) 8) >= 0) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2051, (short) 0, + if (KMInteger.unsignedByteArrayCompare(scratchPad, (short) 0, firstJan2050, (short) 0, (short) 8) < 0) { Util.arrayCopyNonAtomic(firstJan2020, (short) 0, scratchPad, (short) 8, (short) 8); @@ -90,7 +89,7 @@ public static short convertToDate(short time, byte[] scratchPad, (short) 8); } else { from2020 = false; - Util.arrayCopyNonAtomic(firstJan2051, (short) 0, scratchPad, (short) 8, + Util.arrayCopyNonAtomic(firstJan2050, (short) 0, scratchPad, (short) 8, (short) 8); subtract(scratchPad, (short) 0, (short) 8, (short) 16); Util.arrayCopyNonAtomic(scratchPad, (short) 16, scratchPad, (short) 0, @@ -351,7 +350,7 @@ public static void add(byte[] buf, short op1, short op2, short result) { byte carry = 0; short tmp; short val1 = 0; - short val2 = 0; + short val2 = 0; while (index >= 0) { val1 = (short) (buf[(short) (op1 + index)] & 0x00FF); val2 = (short) (buf[(short) (op2 + index)] & 0x00FF); @@ -395,7 +394,7 @@ public static short countTemporalCount(byte[] bufTime, short timeOff, scratchPad, (short) (offset + 8 - timeLen), timeLen); - Util.arrayCopyNonAtomic(oneMonthMsec, (short) 0, scratchPad, (short) (offset + 8), + Util.arrayCopyNonAtomic(ThirtDaysMonthMsec, (short) 0, scratchPad, (short) (offset + 8), (short) 8); return divide(scratchPad, (short) 0, (short) 8, (short) 16); } diff --git a/Applet/src/com/android/javacard/keymaster/KMArray.java b/Applet/src/com/android/javacard/keymaster/KMArray.java index bfa09269..2ffc18ea 100644 --- a/Applet/src/com/android/javacard/keymaster/KMArray.java +++ b/Applet/src/com/android/javacard/keymaster/KMArray.java @@ -114,6 +114,11 @@ public short length() { return Util.getShort(heap, (short) (instanceTable[KM_ARRAY_OFFSET] + TLV_HEADER_SIZE + 2)); } + public short setLength(short len) { + return Util.setShort(heap, + (short) (KMType.instanceTable[KM_ARRAY_OFFSET] + TLV_HEADER_SIZE + 2), len); + } + public byte[] getBuffer() { return heap; } diff --git a/Applet/src/com/android/javacard/keymaster/KMDecoder.java b/Applet/src/com/android/javacard/keymaster/KMDecoder.java index 6fe3189d..b736f147 100644 --- a/Applet/src/com/android/javacard/keymaster/KMDecoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMDecoder.java @@ -170,6 +170,7 @@ private short decodeKeyParam(short exp) { short tagClass; short allowedType; short obj; + short arrPos = 0; // For each tag in payload ... while (index < payloadLength) { tagFound = false; @@ -183,7 +184,7 @@ private short decodeKeyParam(short exp) { if (tagType == allowedType) { // then decodeByteBlob and add that to the array. obj = decode(tagClass); - KMArray.cast(vals).add(index, obj); + KMArray.cast(vals).add(arrPos++, obj); tagFound = true; break; } @@ -195,6 +196,7 @@ private short decodeKeyParam(short exp) { index++; } } + KMArray.cast(vals).setLength(arrPos); return KMKeyParameters.instance(vals); } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java b/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java index bd6edf4a..9012fbc4 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java @@ -35,7 +35,6 @@ public class KMKeyParameters extends KMType { private static final short[] hwEnforcedTagArr = { // HW Enforced - KMType.ENUM_TAG, KMType.ORIGIN, KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, KMType.ENUM_TAG, KMType.ALGORITHM, KMType.UINT_TAG, KMType.KEYSIZE, @@ -54,7 +53,6 @@ public class KMKeyParameters extends KMType { KMType.BOOL_TAG, KMType.ROLLBACK_RESISTANCE, KMType.ENUM_TAG, KMType.USER_AUTH_TYPE, KMType.BOOL_TAG, KMType.UNLOCKED_DEVICE_REQUIRED, - KMType.BOOL_TAG, KMType.RESET_SINCE_ID_ROTATION, KMType.BOOL_TAG, KMType.BOOTLOADER_ONLY, KMType.BOOL_TAG, KMType.EARLY_BOOT_ONLY, KMType.UINT_TAG, KMType.MAX_USES_PER_BOOT, diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index c171400c..ae378924 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -46,7 +46,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe // Magic number version public static final byte KM_MAGIC_NUMBER = (byte) 0x81; // MSB byte is for Major version and LSB byte is for Minor version. - public static final short CURRENT_PACKAGE_VERSION = 0x0200; // 2.0 + public static final short CURRENT_PACKAGE_VERSION = 0x0201; // 2.1 // "Keymaster HMAC Verification" - used for HMAC key verification. public static final byte[] sharingCheck = { @@ -351,6 +351,7 @@ protected void validateApduHeader(APDU apdu) { @Override public void process(APDU apdu) { try { + resetData(); // Handle the card reset status before processing apdu. if (repository.isPowerResetEventOccurred()) { // Release all the operation instances. @@ -546,7 +547,6 @@ && isProvisioningComplete())) { freeOperations(); sendError(apdu, KMError.GENERIC_UNKNOWN_ERROR); } finally { - resetData(); repository.clean(); } } @@ -579,6 +579,7 @@ private void freeOperations() { private void processEarlyBootEndedCmd(APDU apdu) { repository.setEarlyBootEndedStatus(true); + sendError(apdu, KMError.OK); } private void processDeviceLockedCmd(APDU apdu) { @@ -990,7 +991,7 @@ private void processGetKeyCharacteristicsCmd(APDU apdu) { 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) { + || 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()) { @@ -1163,31 +1164,6 @@ private void processComputeSharedHmacCmd(APDU apdu) { sendOutgoing(apdu); } - private boolean isKeyUpgradeRequired(short tag, short systemParam) { - // validate the tag and check if key needs upgrade. - tmpVariables[0] = KMKeyParameters.findTag(KMType.UINT_TAG, tag, data[HW_PARAMETERS]); - tmpVariables[0] = KMIntegerTag.cast(tmpVariables[0]).getValue(); - tmpVariables[1] = KMInteger.uint_8((byte) 0); - if (tmpVariables[0] != KMType.INVALID_VALUE) { - // OS version in key characteristics must be less the OS version stored in Javacard or the - // stored version must be zero. Then only upgrade is allowed else it is invalid argument. - if ((tag == KMType.OS_VERSION - && KMInteger.compare(tmpVariables[0], systemParam) == 1 - && KMInteger.compare(systemParam, tmpVariables[1]) == 0)) { - // Key needs upgrade. - return true; - } else if ((KMInteger.compare(tmpVariables[0], systemParam) == -1)) { - // Each os version or patch level associated with the key must be less than it's - // corresponding value stored in Javacard, then only upgrade is allowed otherwise it - // is invalid argument. - return true; - } else if (KMInteger.compare(tmpVariables[0], systemParam) == 1) { - KMException.throwIt(KMError.INVALID_ARGUMENT); - } - } - return false; - } - private void processUpgradeKeyCmd(APDU apdu) { // Receive the incoming request fully from the master into buffer. receiveIncoming(apdu); @@ -1590,14 +1566,14 @@ private void addAttestationIds(KMAttestationCert cert) { KMByteBlob.cast(storedAttId).length())) { KMException.throwIt(KMError.CANNOT_ATTEST_IDS); } - // Return INVALID_TAG if Attestation IDs does not match. + // Return CANNOT_ATTEST_IDS if Attestation IDs does not match. if ((KMByteBlob.cast(storedAttId).length() != KMByteBlob.cast(attIdTagValue).length()) || (0 != Util.arrayCompare(KMByteBlob.cast(storedAttId).getBuffer(), KMByteBlob.cast(storedAttId).getStartOff(), KMByteBlob.cast(attIdTagValue).getBuffer(), KMByteBlob.cast(attIdTagValue).getStartOff(), KMByteBlob.cast(storedAttId).length()))) { - KMException.throwIt(KMError.INVALID_TAG); + KMException.throwIt(KMError.CANNOT_ATTEST_IDS); } cert.extensionTag(attIdTag, true); } @@ -2367,6 +2343,25 @@ private void processBeginOperationCmd(APDU apdu) { sendOutgoing(apdu); } + private boolean isDigestSupported(byte alg, byte digest) { + switch (alg) { + case KMType.RSA: + case KMType.EC: + if (digest != KMType.DIGEST_NONE && digest != KMType.SHA2_256) { + return false; + } + break; + case KMType.HMAC: + if (digest != KMType.SHA2_256) { + return false; + } + break; + default: + break; + } + return true; + } + private void authorizeAlgorithm(KMOperationState op) { short alg = KMEnumTag.getValue(KMType.ALGORITHM, data[HW_PARAMETERS]); if (alg == KMType.INVALID_VALUE) { @@ -2430,7 +2425,8 @@ private void authorizeDigest(KMOperationState op) { break; case KMType.EC: case KMType.HMAC: - if (param == KMType.INVALID_VALUE) { + if (param == KMType.INVALID_VALUE || + !isDigestSupported(op.getAlgorithm(), op.getDigest())) { KMException.throwIt(KMError.UNSUPPORTED_DIGEST); } break; @@ -2447,7 +2443,7 @@ private void authorizePadding(KMOperationState op) { KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PADDING, data[KEY_PARAMETERS]); if (param != KMType.INVALID_VALUE) { if (KMEnumArrayTag.cast(param).length() != 1) { - KMException.throwIt(KMError.INVALID_ARGUMENT); + KMException.throwIt(KMError.UNSUPPORTED_PADDING_MODE); } param = KMEnumArrayTag.cast(param).get((short) 0); if (!KMEnumArrayTag.cast(paddings).contains(param)) { @@ -2471,13 +2467,21 @@ private void authorizePadding(KMOperationState op) { && param != KMType.RSA_PKCS1_1_5_ENCRYPT) { KMException.throwIt(KMError.UNSUPPORTED_PADDING_MODE); } - if (param == KMType.PADDING_NONE && op.getDigest() != KMType.DIGEST_NONE) { + if ((param == KMType.PADDING_NONE || param == KMType.RSA_PKCS1_1_5_ENCRYPT) + && op.getDigest() != KMType.DIGEST_NONE) { KMException.throwIt(KMError.INCOMPATIBLE_DIGEST); } if ((param == KMType.RSA_OAEP || param == KMType.RSA_PSS) && op.getDigest() == KMType.DIGEST_NONE) { KMException.throwIt(KMError.INCOMPATIBLE_DIGEST); } + if (op.getPurpose() == KMType.SIGN || op.getPurpose() == KMType.VERIFY + || param == KMType.RSA_OAEP) { + // Digest is mandatory in these cases. + if (!isDigestSupported(op.getAlgorithm(), op.getDigest())) { + KMException.throwIt(KMError.UNSUPPORTED_DIGEST); + } + } op.setPadding((byte) param); break; case KMType.DES: @@ -3335,7 +3339,7 @@ private void importRSAKey(byte[] scratchPad) { } if(Util.arrayCompare(F4, (short)0, KMByteBlob.cast(pubKeyExp).getBuffer(), KMByteBlob.cast(pubKeyExp).getStartOff(), (short)F4.length) != 0) { - KMException.throwIt(KMError.INVALID_ARGUMENT); + KMException.throwIt(KMError.IMPORT_PARAMETER_MISMATCH); } tmpVariables[4] = 0; // index in scratchPad for update parameters. // validate public exponent if present in key params - it must be 0x010001 @@ -3775,10 +3779,6 @@ private static void validateHmacKey() { if (KMType.INVALID_VALUE == tmpVariables[0]) { KMException.throwIt(KMError.UNSUPPORTED_DIGEST); } - - if (KMEnumArrayTag.contains(KMType.DIGEST, KMType.DIGEST_NONE, data[KEY_PARAMETERS])) { - KMException.throwIt(KMError.UNSUPPORTED_DIGEST); - } // Strongbox supports only SHA256. if (!KMEnumArrayTag.contains(KMType.DIGEST, KMType.SHA2_256, data[KEY_PARAMETERS])) { KMException.throwIt(KMError.UNSUPPORTED_DIGEST); @@ -4309,6 +4309,7 @@ private boolean isKeyUpgradeRequired(short keyBlob, short appId, short appData, short index = 0; short tag; short systemParam; + boolean isKeyUpgradeRequired = false; while(index < 16) { tag = Util.getShort(scratchPad, index); systemParam = Util.getShort(scratchPad, (short) (index + 2)); @@ -4323,12 +4324,12 @@ private boolean isKeyUpgradeRequired(short keyBlob, short appId, short appData, && KMInteger.compare(tagValue, systemParam) == 1 && KMInteger.compare(systemParam, zero) == 0)) { // Key needs upgrade. - return true; + isKeyUpgradeRequired = true; } else if ((KMInteger.compare(tagValue, systemParam) == -1)) { // Each os version or patch level associated with the key must be less than it's // corresponding value stored in Javacard, then only upgrade is allowed otherwise it // is invalid argument. - return true; + isKeyUpgradeRequired = true; } else if (KMInteger.compare(tagValue, systemParam) == 1) { KMException.throwIt(KMError.INVALID_ARGUMENT); } @@ -4337,7 +4338,7 @@ private boolean isKeyUpgradeRequired(short keyBlob, short appId, short appData, } index += 4; } - return false; + return isKeyUpgradeRequired; } private short readKeyBlobVersion(short keyBlob) { diff --git a/Applet/src/com/android/javacard/keymaster/KMRepository.java b/Applet/src/com/android/javacard/keymaster/KMRepository.java index df380507..1d018d22 100644 --- a/Applet/src/com/android/javacard/keymaster/KMRepository.java +++ b/Applet/src/com/android/javacard/keymaster/KMRepository.java @@ -389,6 +389,7 @@ public void reclaimMemory(short length) { if (reclaimIndex[0] < heapIndex[0]) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } + Util.arrayFillNonAtomic(heap, reclaimIndex[0], length, (byte) 0); reclaimIndex[0] += length; } diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index 17e5bb4c..208b9887 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -1483,7 +1483,7 @@ Return<::android::hardware::keymaster::V4_1::ErrorCode> JavacardKeymaster4Device } /* Convert input data to cbor format */ - array.add(passwordOnly); + array.add((passwordOnly ? 1 : 0)); cborConverter_.addVerificationToken(array, verificationToken, asn1ParamsVerified); std::vector cborData = array.encode();