From f9ad6eb2db193fd020e66cb7aefec0162350b1d0 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Fri, 13 May 2022 01:20:03 +0000 Subject: [PATCH] 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 | 82 ++++++++++--------- .../javacard/keymaster/KMRepository.java | 1 + .../4.1/JavacardKeymaster4Device.cpp | 2 +- 12 files changed, 80 insertions(+), 72 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 5a2a6f82..f7dd2ca5 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) { @@ -985,6 +986,7 @@ 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]).isValid()) { data[APP_ID] = KMType.INVALID_VALUE; } @@ -1155,31 +1157,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); @@ -1582,14 +1559,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); } @@ -2359,6 +2336,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) { @@ -2422,7 +2418,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; @@ -2439,7 +2436,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)) { @@ -2463,13 +2460,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: @@ -3327,7 +3332,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 @@ -3767,10 +3772,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); @@ -4301,6 +4302,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)); @@ -4315,12 +4317,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); } @@ -4329,7 +4331,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();