From fea835b0d3193a3fa212317b8d545e92e04ca487 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Sun, 10 Apr 2022 07:57:11 +0000 Subject: [PATCH 1/6] Mac keyparams in generateKey, importKey and importWrappedKey and send to attestKey --- .../android/javacard/keymaster/KMEncoder.java | 2 +- .../javacard/keymaster/KMKeymasterApplet.java | 80 +++++++++++++---- HAL/JavacardKeyMintDevice.cpp | 86 +++++++++++++------ 3 files changed, 124 insertions(+), 44 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/Applet/src/com/android/javacard/keymaster/KMEncoder.java index 549b3497..0ba1986c 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -386,7 +386,7 @@ private void encodeIntegerTag(short obj) { private void encodeBignumTag(short obj) { writeTag(KMBignumTag.getTagType(obj), KMBignumTag.getKey(obj)); - encode(KMBignumTag.getValue(obj)); + encode(KMBignumTag.cast(obj).getValue()); } private void encodeBytesTag(short obj) { diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 8addee71..9da3d672 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -44,7 +44,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe public static final byte[] F4 = {0x01, 0x00, 0x01}; public static final byte AES_BLOCK_SIZE = 16; public static final byte DES_BLOCK_SIZE = 8; - public static final short MAX_LENGTH = 15000; + public static final short MAX_LENGTH = 10000; public static final short MASTER_KEY_SIZE = 128; public static final short WRAPPING_KEY_SIZE = 32; public static final short MAX_OPERATIONS_COUNT = 4; @@ -2909,17 +2909,15 @@ private boolean validateHwToken(short hwToken, byte[] scratchPad) { } private short importKeyCmd(APDU apdu){ - short cmd = KMArray.instance((short) 6); + short cmd = KMArray.instance((short) 3); // Arguments short params = KMKeyParameters.expAny(); KMArray.cast(cmd).add((short) 0, params); KMArray.cast(cmd).add((short) 1, KMEnum.instance(KMType.KEY_FORMAT)); KMArray.cast(cmd).add((short) 2, KMByteBlob.exp()); - KMArray.cast(cmd).add((short) 3, KMByteBlob.exp()); //attest key - KMArray.cast(cmd).add((short) 4, params); //attest key params - KMArray.cast(cmd).add((short) 5, KMByteBlob.exp()); //issuer return receiveIncoming(apdu, cmd); } + private void processImportKeyCmd(APDU apdu) { // Receive the incoming request fully from the master into buffer. short cmd = importKeyCmd(apdu); @@ -2927,9 +2925,6 @@ private void processImportKeyCmd(APDU apdu) { data[KEY_PARAMETERS] = KMArray.cast(cmd).get((short) 0); short keyFmt = KMArray.cast(cmd).get((short) 1); data[IMPORTED_KEY_BLOB] = KMArray.cast(cmd).get((short) 2); - data[ATTEST_KEY_BLOB] = KMArray.cast(cmd).get((short) 3); - data[ATTEST_KEY_PARAMS] = KMArray.cast(cmd).get((short) 4); - data[ATTEST_KEY_ISSUER] = KMArray.cast(cmd).get((short) 5); keyFmt = KMEnum.cast(keyFmt).getVal(); data[CERTIFICATE] = KMArray.instance((short)0); //by default the cert is empty. @@ -2968,6 +2963,9 @@ private void validateImportKey(short params, short keyFmt){ } private void importKey(APDU apdu, short keyFmt, byte[] scratchPad) { + // Take backup of the KeyParams before they get updated. The original + // key params are required to generate MAC in macKeyParams() function. + short keyParams = data[KEY_PARAMETERS]; validateImportKey(data[KEY_PARAMETERS], keyFmt); // Check algorithm and dispatch to appropriate handler. short alg = KMEnumTag.getValue(KMType.ALGORITHM, data[KEY_PARAMETERS]); @@ -2991,8 +2989,9 @@ private void importKey(APDU apdu, short keyFmt, byte[] scratchPad) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); break; } + // MAC the KeyParameters. + short keyParamsMac = macKeyParams(keyParams, scratchPad); makeKeyCharacteristics( scratchPad); - generateAttestation(data[ATTEST_KEY_BLOB], data[ATTEST_KEY_PARAMS],scratchPad); createEncryptedKeyBlob(scratchPad); // Remove custom tags from key characteristics short teeParams = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getTeeEnforced(); @@ -3004,7 +3003,7 @@ private void importKey(APDU apdu, short keyFmt, byte[] scratchPad) { KMArray.cast(resp).add((short) 0, KMInteger.uint_16(KMError.OK)); KMArray.cast(resp).add((short) 1, data[KEY_BLOB]); KMArray.cast(resp).add((short) 2, data[KEY_CHARACTERISTICS]); - KMArray.cast(resp).add((short) 3, data[CERTIFICATE]); + KMArray.cast(resp).add((short) 3, keyParamsMac); sendOutgoing(apdu, resp); } @@ -3434,6 +3433,8 @@ private void processGenerateKey(APDU apdu) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); break; } + // MAC the KeyParameters. + short keyParamsMac = macKeyParams(data[KEY_PARAMETERS], scratchPad); // create key blob and associated attestation. data[ORIGIN] = KMType.GENERATED; @@ -3445,10 +3446,11 @@ private void processGenerateKey(APDU apdu) { KMKeyParameters.cast(teeParams).deleteCustomTags(); } // prepare the response - short resp = KMArray.instance((short) 3); + short resp = KMArray.instance((short) 4); KMArray.cast(resp).add((short) 0, KMInteger.uint_16(KMError.OK)); KMArray.cast(resp).add((short) 1, data[KEY_BLOB]); KMArray.cast(resp).add((short) 2, data[KEY_CHARACTERISTICS]); + KMArray.cast(resp).add((short) 3, keyParamsMac); sendOutgoing(apdu, resp); } @@ -3456,12 +3458,13 @@ private short generateAttestKeyCmd(APDU apdu) { short params = KMKeyParameters.expAny(); short blob = KMByteBlob.exp(); // Array of expected arguments - short cmd = KMArray.instance((short) 5); + short cmd = KMArray.instance((short) 6); KMArray.cast(cmd).add((short) 0, blob); // key blob KMArray.cast(cmd).add((short) 1, params); // keyparamters to be attested. KMArray.cast(cmd).add((short) 2, blob); // attest key blob KMArray.cast(cmd).add((short) 3, params); // attest key params KMArray.cast(cmd).add((short) 4, blob); // attest issuer + KMArray.cast(cmd).add((short) 5, blob); // keyparams mac. return receiveIncoming(apdu, cmd); } @@ -3486,6 +3489,7 @@ private void processAttestKeyCmd(APDU apdu) { data[ATTEST_KEY_BLOB] = KMArray.cast(cmd).get((short) 2); data[ATTEST_KEY_PARAMS] = KMArray.cast(cmd).get((short) 3); data[ATTEST_KEY_ISSUER] = KMArray.cast(cmd).get((short) 4); + short keyParamsMac = KMArray.cast(cmd).get((short) 5); data[CERTIFICATE] = KMArray.instance((short) 0); // by default the cert is empty. @@ -3501,14 +3505,16 @@ private void processAttestKeyCmd(APDU apdu) { // Check if key requires upgrade. The KeyBlob is parsed inside isKeyUpgradeRequired // function itself. parseEncryptedKeyBlob(data[KEY_BLOB], data[APP_ID], data[APP_DATA], scratchPad, KEYBLOB_CURRENT_VERSION); + // Validate KeyParams Mac + if (!validateKeyParamsMac(data[KEY_PARAMETERS], keyParamsMac, scratchPad)) { + KMException.throwIt(KMError.INVALID_KEY_BLOB); + } // The key which is being attested should be asymmetric i.e. RSA or EC short alg = KMEnumTag.getValue(KMType.ALGORITHM, data[HW_PARAMETERS]); - if (alg != KMType.RSA && alg != KMType.EC) { - KMException.throwIt(KMError.INCOMPATIBLE_ALGORITHM); + if (alg == KMType.RSA || alg == KMType.EC) { + // Build certificate + generateAttestation(data[ATTEST_KEY_BLOB], data[ATTEST_KEY_PARAMS], scratchPad); } - // Build certificate - generateAttestation(data[ATTEST_KEY_BLOB], data[ATTEST_KEY_PARAMS], scratchPad); - short resp = KMArray.instance((short) 2); KMArray.cast(resp).add((short) 0, KMInteger.uint_16(KMError.OK)); KMArray.cast(resp).add((short) 1, data[CERTIFICATE]); @@ -3788,6 +3794,46 @@ private static void makeKeyCharacteristics(byte[] scratchPad) { KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).setTeeEnforced(data[TEE_PARAMETERS]); } + private short macKeyParams(short keyParams, byte[] scratchPad) { + // For Symmetric Keys no need to Mac the Key parameters. As for symmetric keys + // attestation is not done. + if (SYM_KEY_TYPE == getKeyType(keyParams)) { + return KMByteBlob.instance((short) 0); + } + short len = encodeToApduBuffer(keyParams, scratchPad, (short) 0, (short) 1024 /* Max Size */); + + short derivedKeyLen = seProvider.hmacKDF( + kmDataStore.getMasterKey(), + KMByteBlob.cast(data[SECRET]).getBuffer(), + KMByteBlob.cast(data[SECRET]).getStartOff(), + KMByteBlob.cast(data[SECRET]).length(), + scratchPad, + len); + if (derivedKeyLen < 16) { + KMException.throwIt(KMError.UNKNOWN_ERROR); + } + derivedKeyLen = 16; + + short signLen = seProvider.hmacSign(scratchPad, len, derivedKeyLen, + scratchPad, (short) 0, len, scratchPad, (short) (derivedKeyLen + len)); + return KMByteBlob.instance(scratchPad, (short) (derivedKeyLen + len), signLen); + } + + private boolean validateKeyParamsMac(short keyParams, short keyParamsMac, byte[] scratchPad) { + short ptr = macKeyParams(keyParams, scratchPad); + if (KMByteBlob.cast(ptr).length() != KMByteBlob.cast(keyParamsMac).length()) { + return false; + } + if (0 != Util.arrayCompare( + KMByteBlob.cast(ptr).getBuffer(), + KMByteBlob.cast(ptr).getStartOff(), + KMByteBlob.cast(keyParamsMac).getBuffer(), + KMByteBlob.cast(keyParamsMac).getStartOff(), + KMByteBlob.cast(keyParamsMac).length())) { + return false; + } + return true; + } private static void createEncryptedKeyBlob(byte[] scratchPad) { // make root of trust blob diff --git a/HAL/JavacardKeyMintDevice.cpp b/HAL/JavacardKeyMintDevice.cpp index faa1cd43..0cb1bec6 100644 --- a/HAL/JavacardKeyMintDevice.cpp +++ b/HAL/JavacardKeyMintDevice.cpp @@ -46,13 +46,6 @@ ScopedAStatus JavacardKeyMintDevice::defaultHwInfo(KeyMintHardwareInfo* info) { return ScopedAStatus::ok(); } -static inline bool findTag(const vector& params, Tag tag) { - size_t size = params.size(); - for (size_t i = 0; i < size; ++i) { - if (tag == params[i].tag) return true; - } - return false; -} ScopedAStatus JavacardKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) { uint64_t tsRequired = 1; @@ -79,6 +72,7 @@ ScopedAStatus JavacardKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) ScopedAStatus JavacardKeyMintDevice::generateKey(const vector& keyParams, const optional& attestationKey, KeyCreationResult* creationResult) { + vector keyParamsMac; cppbor::Array array; // add key params cbor_.addKeyparameters(array, keyParams); @@ -88,7 +82,8 @@ ScopedAStatus JavacardKeyMintDevice::generateKey(const vector& key return km_utils::kmError2ScopedAStatus(err); } if (!cbor_.getBinaryArray(item, 1, creationResult->keyBlob) || - !cbor_.getKeyCharacteristics(item, 2, creationResult->keyCharacteristics)) { + !cbor_.getKeyCharacteristics(item, 2, creationResult->keyCharacteristics) || + !cbor_.getBinaryArray(item, 3, keyParamsMac)) { LOG(ERROR) << "Error in decoding og response in generateKey."; return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); } @@ -103,14 +98,15 @@ ScopedAStatus JavacardKeyMintDevice::generateKey(const vector& key attestKeyArray.add(creationResult->keyBlob); cbor_.addKeyparameters(attestKeyArray, keyParams); cbor_.addAttestationKey(attestKeyArray, attestationKey); - auto [item, err] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); - if (err != KM_ERROR_OK) { - LOG(ERROR) << "Failed in attestKey err: "; - return km_utils::kmError2ScopedAStatus(err); + attestKeyArray.add(keyParamsMac); + auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); + if (error != KM_ERROR_OK) { + LOG(ERROR) << "Failed in attestKey err: "; + return km_utils::kmError2ScopedAStatus(error); } - if (!cbor_.getCertificateChain(item, 1, creationResult->certificateChain)) { - LOG(ERROR) << "Error in decoding og response in generateKey."; - return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); + if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) { + LOG(ERROR) << "Error in decoding og response in generateKey."; + return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); } } return ScopedAStatus::ok(); @@ -133,21 +129,14 @@ ScopedAStatus JavacardKeyMintDevice::importKey(const vector& keyPa const optional& attestationKey, KeyCreationResult* creationResult) { + vector keyParamsMac; cppbor::Array request; - vector updatedParams(keyParams); - // Add CREATION_DATETIME if required, as secure element is not having clock. - if (!findTag(keyParams, Tag::CREATION_DATETIME) && !findTag(keyParams, Tag::ACTIVE_DATETIME)) { - updatedParams.push_back(km_utils::kmParam2Aidl( - keymaster_param_date(KM_TAG_CREATION_DATETIME, java_time(time(nullptr))))); - } // add key params - cbor_.addKeyparameters(request, updatedParams); + cbor_.addKeyparameters(request, keyParams); // add key format request.add(Uint(static_cast(keyFormat))); // add key data request.add(Bstr(keyData)); - // add attestation key if any - cbor_.addAttestationKey(request, attestationKey); auto [item, err] = card_->sendRequest(Instruction::INS_IMPORT_KEY_CMD, request); if (err != KM_ERROR_OK) { @@ -156,10 +145,32 @@ ScopedAStatus JavacardKeyMintDevice::importKey(const vector& keyPa } if (!cbor_.getBinaryArray(item, 1, creationResult->keyBlob) || !cbor_.getKeyCharacteristics(item, 2, creationResult->keyCharacteristics) || - !cbor_.getCertificateChain(item, 3, creationResult->certificateChain)) { + !cbor_.getBinaryArray(item, 3, keyParamsMac)) { LOG(ERROR) << "Error in decoding response in importKey."; return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); } + + AuthorizationSet paramSet; + paramSet.Reinitialize(KmParamSet(keyParams)); + // Call attestKey only Asymmetric algorithms. + keymaster_algorithm_t algorithm; + paramSet.GetTagValue(TAG_ALGORITHM, &algorithm); + if (algorithm == KM_ALGORITHM_RSA || algorithm == KM_ALGORITHM_EC) { + cppbor::Array attestKeyArray; + attestKeyArray.add(creationResult->keyBlob); + cbor_.addKeyparameters(attestKeyArray, keyParams); + cbor_.addAttestationKey(attestKeyArray, attestationKey); + attestKeyArray.add(keyParamsMac); + auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); + if (error != KM_ERROR_OK) { + LOG(ERROR) << "Failed in attestKey err: "; + return km_utils::kmError2ScopedAStatus(error); + } + if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) { + LOG(ERROR) << "Error in decoding of response in importKey."; + return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); + } + } return ScopedAStatus::ok(); } @@ -181,6 +192,7 @@ ScopedAStatus JavacardKeyMintDevice::importWrappedKey(const vector& wra std::vector tag; vector authList; KeyFormat keyFormat; + vector keyParamsMac; std::vector wrappedKeyDescription; keymaster_error_t errorCode = parseWrappedKey(wrappedKeyData, iv, transitKey, secureKey, tag, authList, keyFormat, wrappedKeyDescription); @@ -205,10 +217,32 @@ ScopedAStatus JavacardKeyMintDevice::importWrappedKey(const vector& wra } if (!cbor_.getBinaryArray(item, 1, creationResult->keyBlob) || !cbor_.getKeyCharacteristics(item, 2, creationResult->keyCharacteristics) || - !cbor_.getCertificateChain(item, 3, creationResult->certificateChain)) { + !cbor_.getBinaryArray(item, 3, keyParamsMac)) { LOG(ERROR) << "Error in decoding the response in importWrappedKey."; return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); } + + AuthorizationSet paramSet; + paramSet.Reinitialize(KmParamSet(authList)); + // Call attestKey only Asymmetric algorithms. + keymaster_algorithm_t algorithm; + paramSet.GetTagValue(TAG_ALGORITHM, &algorithm); + if (algorithm == KM_ALGORITHM_RSA || algorithm == KM_ALGORITHM_EC) { + cppbor::Array attestKeyArray; + attestKeyArray.add(creationResult->keyBlob); + cbor_.addKeyparameters(attestKeyArray, authList); + attestKeyArray.add(keyParamsMac); + cbor_.addAttestationKey(attestKeyArray, std::nullopt); + auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); + if (error != KM_ERROR_OK) { + LOG(ERROR) << "Failed in attestKey err: "; + return km_utils::kmError2ScopedAStatus(error); + } + if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) { + LOG(ERROR) << "Error in decoding of response in importWrappedKey."; + return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); + } + } return ScopedAStatus::ok(); } From 3583914fd218e3deee0458650f51e4666ff96da4 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Mon, 11 Apr 2022 23:59:52 +0000 Subject: [PATCH 2/6] Modified the mac generation logic for keyparams --- .../javacard/keymaster/KMKeymasterApplet.java | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 9da3d672..0827882e 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -109,6 +109,8 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe }; public static final short MAX_COSE_BUF_SIZE = (short) 1024; + // Maximum possible encoded keyparams size + public static final short MAX_KEY_PARAMS_BUF_SIZE = (short) 2048; // Top 32 commands are reserved for provisioning. private static final byte KEYMINT_CMD_APDU_START = 0x20; @@ -2989,10 +2991,10 @@ private void importKey(APDU apdu, short keyFmt, byte[] scratchPad) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); break; } - // MAC the KeyParameters. - short keyParamsMac = macKeyParams(keyParams, scratchPad); makeKeyCharacteristics( scratchPad); createEncryptedKeyBlob(scratchPad); + // MAC the KeyParameters. + short keyParamsMac = macKeyParams(keyParams, scratchPad); // Remove custom tags from key characteristics short teeParams = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getTeeEnforced(); if(teeParams != KMType.INVALID_VALUE) { @@ -3433,13 +3435,12 @@ private void processGenerateKey(APDU apdu) { KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); break; } - // MAC the KeyParameters. - short keyParamsMac = macKeyParams(data[KEY_PARAMETERS], scratchPad); - // create key blob and associated attestation. data[ORIGIN] = KMType.GENERATED; makeKeyCharacteristics(scratchPad); createEncryptedKeyBlob(scratchPad); + // MAC the KeyParameters. + short keyParamsMac = macKeyParams(data[KEY_PARAMETERS], scratchPad); // Remove custom tags from key characteristics short teeParams = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getTeeEnforced(); if(teeParams != KMType.INVALID_VALUE) { @@ -3800,23 +3801,18 @@ private short macKeyParams(short keyParams, byte[] scratchPad) { if (SYM_KEY_TYPE == getKeyType(keyParams)) { return KMByteBlob.instance((short) 0); } - short len = encodeToApduBuffer(keyParams, scratchPad, (short) 0, (short) 1024 /* Max Size */); + short len = encodeToApduBuffer(keyParams, scratchPad, (short) 0, MAX_KEY_PARAMS_BUF_SIZE); - short derivedKeyLen = seProvider.hmacKDF( - kmDataStore.getMasterKey(), - KMByteBlob.cast(data[SECRET]).getBuffer(), - KMByteBlob.cast(data[SECRET]).getStartOff(), - KMByteBlob.cast(data[SECRET]).length(), + short signLen = seProvider.hmacSign( + KMByteBlob.cast(data[AUTH_TAG]).getBuffer(), + KMByteBlob.cast(data[AUTH_TAG]).getStartOff(), + KMByteBlob.cast(data[AUTH_TAG]).length(), + scratchPad, + (short) 0, + len, scratchPad, len); - if (derivedKeyLen < 16) { - KMException.throwIt(KMError.UNKNOWN_ERROR); - } - derivedKeyLen = 16; - - short signLen = seProvider.hmacSign(scratchPad, len, derivedKeyLen, - scratchPad, (short) 0, len, scratchPad, (short) (derivedKeyLen + len)); - return KMByteBlob.instance(scratchPad, (short) (derivedKeyLen + len), signLen); + return KMByteBlob.instance(scratchPad, len, signLen); } private boolean validateKeyParamsMac(short keyParams, short keyParamsMac, byte[] scratchPad) { From 5ea05ac3b37816dd1c8954e25e4113af9152c042 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Tue, 12 Apr 2022 07:02:54 +0000 Subject: [PATCH 3/6] Updated the attestation flow and indentation --- .../javacard/keymaster/KMBignumTag.java | 32 +-- .../android/javacard/keymaster/KMByteTag.java | 84 +++---- .../javacard/keymaster/KMKeymasterApplet.java | 233 ++++++++---------- .../android/javacard/keymaster/KMType.java | 8 + 4 files changed, 169 insertions(+), 188 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMBignumTag.java b/Applet/src/com/android/javacard/keymaster/KMBignumTag.java index 7b020314..28b63cb3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMBignumTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMBignumTag.java @@ -30,11 +30,6 @@ public class KMBignumTag extends KMTag { private static KMBignumTag prototype; - // The allowed tag keys of type bool tag - private static final short[] tags = { - CERTIFICATE_SERIAL_NUM, - }; - private KMBignumTag() { } @@ -56,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) { @@ -104,13 +92,17 @@ 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 CERTIFICATE_SERIAL_NUM: + if (valueLen > MAX_CERTIFICATE_SERIAL_SIZE) { + return false; + } + break; + default: + return false; } - return false; + return true; } } diff --git a/Applet/src/com/android/javacard/keymaster/KMByteTag.java b/Applet/src/com/android/javacard/keymaster/KMByteTag.java index f896722d..e33cc4db 100644 --- a/Applet/src/com/android/javacard/keymaster/KMByteTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMByteTag.java @@ -30,34 +30,6 @@ 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, - 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, - CERTIFICATE_SERIAL_NUM, - CERTIFICATE_SUBJECT_NAME, - }; - private KMByteTag() { } @@ -104,7 +76,8 @@ public static KMByteTag cast(short ptr) { } public short getKey() { - return Util.getShort(heap, (short) (KMType.instanceTable[KM_BYTE_TAG_OFFSET] + TLV_HEADER_SIZE + 2)); + return Util.getShort(heap, + (short) (KMType.instanceTable[KM_BYTE_TAG_OFFSET] + TLV_HEADER_SIZE + 2)); } public short getTagType() { @@ -112,27 +85,50 @@ public short getTagType() { } public short getValue() { - return Util.getShort(heap, (short) (KMType.instanceTable[KM_BYTE_TAG_OFFSET] + TLV_HEADER_SIZE + 4)); + return Util.getShort(heap, + (short) (KMType.instanceTable[KM_BYTE_TAG_OFFSET] + TLV_HEADER_SIZE + 4)); } public short length() { - short blobPtr = Util.getShort(heap, (short) (KMType.instanceTable[KM_BYTE_TAG_OFFSET] + TLV_HEADER_SIZE + 4)); + short blobPtr = Util.getShort(heap, + (short) (KMType.instanceTable[KM_BYTE_TAG_OFFSET] + TLV_HEADER_SIZE + 4)); return KMByteBlob.cast(blobPtr).length(); } - private static boolean validateKey(short key, short keyBlob) { - boolean result = false; - short index = (short) tags.length; - while (--index >= 0) { - if (tags[index] == key) { - result = true; - if(key == APPLICATION_ID || key == APPLICATION_DATA) { - if (KMByteBlob.cast(keyBlob).length() > MAX_APP_ID_APP_DATA_SIZE) { - result = false; - } - } - break; - } + private static boolean validateKey(short key, short byteBlob) { + short valueLen = KMByteBlob.cast(byteBlob).length(); + switch (key) { + case ROOT_OF_TRUST: + case UNIQUE_ID: + case ATTESTATION_APPLICATION_ID: + 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: + case ASSOCIATED_DATA: + case NONCE: + case CONFIRMATION_TOKEN: + case VERIFIED_BOOT_KEY: + case VERIFIED_BOOT_HASH: + case CERTIFICATE_SUBJECT_NAME: + break; + case APPLICATION_ID: + case APPLICATION_DATA: + if (valueLen > MAX_APP_ID_APP_DATA_SIZE) { + return false; + } + break; + case ATTESTATION_CHALLENGE: + if (valueLen > MAX_ATTESTATION_CHALLENGE_SIZE) { + return false; + } + break; + default: + return false; } return result; } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 0827882e..0eb32fe0 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -997,17 +997,8 @@ private void processUpgradeKeyCmd(APDU apdu) { short keyBlob = KMArray.cast(cmd).get((short) 0); data[KEY_PARAMETERS] = KMArray.cast(cmd).get((short) 1); - //tmpVariables[0] - short appId = - KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, data[KEY_PARAMETERS]); - if (appId != KMTag.INVALID_VALUE) { - data[APP_ID] = KMByteTag.cast(appId).getValue(); - } - short appData = - KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, data[KEY_PARAMETERS]); - if (appData != KMTag.INVALID_VALUE) { - data[APP_DATA] = KMByteTag.cast(appData).getValue(); - } + short appId = getApplicationId(data[KEY_PARAMETERS]); + short appData = getApplicationData(data[KEY_PARAMETERS]); data[KEY_BLOB] = KMType.INVALID_VALUE; // Check if the KeyBlob requires upgrade. The KeyBlob is parsed inside isKeyUpgradeRequired @@ -1051,18 +1042,8 @@ private void processExportKeyCmd(APDU apdu) { private void processWrappingKeyBlob(short keyBlob, short wrapParams, byte[] scratchPad) { // Read App Id and App Data if any from un wrapping key params - short appId = - KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, wrapParams); - short appData = - KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, wrapParams); - if (appId != KMTag.INVALID_VALUE) { - appId = KMByteTag.cast(appId).getValue(); - } - if (appData != KMTag.INVALID_VALUE) { - appData = KMByteTag.cast(appData).getValue(); - } - data[APP_ID] = appId; - data[APP_DATA] = appData; + data[APP_ID] = getApplicationId(wrapParams); + data[APP_DATA] = getApplicationData(wrapParams); data[KEY_PARAMETERS] = wrapParams; data[KEY_BLOB] = keyBlob; // Check if key requires upgrade. The KeyBlob is parsed inside isKeyUpgradeRequired @@ -1249,27 +1230,32 @@ private void processFinishImportWrappedKeyCmd(APDU apdu){ } private KMAttestationCert makeCommonCert(byte[] scratchPad) { - short alg = KMKeyParameters.findTag(KMType.ENUM_TAG, KMType.ALGORITHM, data[KEY_PARAMETERS]); + // The Algorithm value can be read from either data[HW_PARAMETERS] or data[KEY_PARAMETERS] + // as the values will be same, and they are cryptographically bound. + short alg = KMKeyParameters.findTag(KMType.ENUM_TAG, KMType.ALGORITHM, data[HW_PARAMETERS]); boolean rsaCert = KMEnumTag.cast(alg).getValue() == KMType.RSA; KMAttestationCert cert = KMAttestationCertImpl.instance(rsaCert, seProvider); - short subject = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.CERTIFICATE_SUBJECT_NAME, data[KEY_PARAMETERS]); + short subject = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.CERTIFICATE_SUBJECT_NAME, + data[KEY_PARAMETERS]); // If no subject name is specified then use the default subject name. - if(subject == KMType.INVALID_VALUE || KMByteTag.cast(subject).length() == 0){ + if (subject == KMType.INVALID_VALUE || KMByteTag.cast(subject).length() == 0) { subject = KMByteBlob.instance(defaultSubject, (short) 0, (short) defaultSubject.length); - }else{ + } else { subject = KMByteTag.cast(subject).getValue(); } cert.subjectName(subject); // Validity period must be specified - short notBefore = KMKeyParameters.findTag(KMType.DATE_TAG, KMType.CERTIFICATE_NOT_BEFORE, data[KEY_PARAMETERS]); - if(notBefore == KMType.INVALID_VALUE){ + short notBefore = KMKeyParameters.findTag(KMType.DATE_TAG, KMType.CERTIFICATE_NOT_BEFORE, + data[KEY_PARAMETERS]); + if (notBefore == KMType.INVALID_VALUE) { KMException.throwIt(KMError.MISSING_NOT_BEFORE); } notBefore = KMIntegerTag.cast(notBefore).getValue(); - short notAfter = KMKeyParameters.findTag(KMType.DATE_TAG, KMType.CERTIFICATE_NOT_AFTER, data[KEY_PARAMETERS]); - if(notAfter == KMType.INVALID_VALUE ){ + short notAfter = KMKeyParameters.findTag(KMType.DATE_TAG, KMType.CERTIFICATE_NOT_AFTER, + data[KEY_PARAMETERS]); + if (notAfter == KMType.INVALID_VALUE ) { KMException.throwIt(KMError.MISSING_NOT_AFTER); } notAfter = KMIntegerTag.cast(notAfter).getValue(); @@ -1295,31 +1281,21 @@ private KMAttestationCert makeCommonCert(byte[] scratchPad) { KMKeyParameters.findTag(KMType.BIGNUM_TAG, KMType.CERTIFICATE_SERIAL_NUM, data[KEY_PARAMETERS]); if (serialNum != KMType.INVALID_VALUE) { serialNum = KMBignumTag.cast(serialNum).getValue(); - }else{ - serialNum= KMByteBlob.instance((short)1); - KMByteBlob.cast(serialNum).add((short)0, (byte)1); + } else { + serialNum= KMByteBlob.instance((short) 1); + KMByteBlob.cast(serialNum).add((short) 0, (byte) 1); } cert.serialNumber(serialNum); return cert; } - private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyParam, short attChallenge, short issuer, - short hwParameters, short swParameters, byte[] scratchPad) { + private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyParam, + short attChallenge, short issuer, short hwParameters, byte[] scratchPad) { KMAttestationCert cert = makeCommonCert(scratchPad); // App Id and App Data, - short appId = KMType.INVALID_VALUE; - short appData = KMType.INVALID_VALUE; - if (attKeyParam != KMType.INVALID_VALUE) { - appId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, attKeyParam); - if (appId != KMTag.INVALID_VALUE) { - appId = KMByteTag.cast(appId).getValue(); - } - appData = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, attKeyParam); - if (appData != KMTag.INVALID_VALUE) { - appData = KMByteTag.cast(appData).getValue(); - } - } + short appId = getApplicationId(attKeyParam); + short appData = getApplicationData(attKeyParam); short origBlob = data[KEY_BLOB]; short pubKey = data[PUB_KEY]; short privKey = data[SECRET]; @@ -1329,9 +1305,9 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara KMException.throwIt(KMError.KEY_REQUIRES_UPGRADE); } short attestationKeySecret = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_SECRET); - short attestParam = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_PARAMS); - attestParam = KMKeyCharacteristics.cast(attestParam).getStrongboxEnforced(); - short attKeyPurpose = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, attestParam); + short attestKeyCharacteristics = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_PARAMS); + short attestKeySbParams = KMKeyCharacteristics.cast(attestKeyCharacteristics).getStrongboxEnforced(); + short attKeyPurpose = KMKeyParameters.findTag(KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, attestKeySbParams); // If the attest key's purpose is not "attest key" then error. if (!KMEnumArrayTag.cast(attKeyPurpose).contains(KMType.ATTEST_KEY)) { KMException.throwIt(KMError.INCOMPATIBLE_PURPOSE); @@ -1340,13 +1316,14 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara if (KMByteBlob.cast(issuer).length() <= 0) { KMException.throwIt(KMError.MISSING_ISSUER_SUBJECT_NAME); } - short alg = KMKeyParameters.findTag(KMType.ENUM_TAG, KMType.ALGORITHM, attestParam); - - if (KMEnumTag.cast(alg).getValue() == KMType.RSA) { + short alg = KMEnumTag.getValue(KMType.ALGORITHM, attestKeySbParams); + if (alg == KMType.RSA) { short attestationKeyPublic = KMArray.cast(data[KEY_BLOB]).get(KEY_BLOB_PUB_KEY); cert.rsaAttestKey(attestationKeySecret, attestationKeyPublic, KMType.ATTESTATION_CERT); - } else { + } else if (alg == KMType.EC) { cert.ecAttestKey(attestationKeySecret, KMType.ATTESTATION_CERT); + } else { + KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); } cert.attestationChallenge(attChallenge); cert.issuer(issuer); @@ -1356,14 +1333,16 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara cert.publicKey(data[PUB_KEY]); // Save attestation application id - must be present. - short attAppId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.ATTESTATION_APPLICATION_ID, data[KEY_PARAMETERS]); + short attAppId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.ATTESTATION_APPLICATION_ID, + data[KEY_PARAMETERS]); if (attAppId == KMType.INVALID_VALUE) { KMException.throwIt(KMError.ATTESTATION_APPLICATION_ID_MISSING); } cert.extensionTag(attAppId, false); // unique id byte blob - uses application id and temporal month count of // creation time. - setUniqueId(cert, scratchPad); + attAppId = KMByteTag.cast(attAppId).getValue(); + setUniqueId(cert, attAppId, scratchPad); // Add Attestation Ids if present addAttestationIds(cert, scratchPad); @@ -1382,25 +1361,25 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara return cert; } - private KMAttestationCert makeSelfSignedCert(short attPrivKey, short attPubKey, byte[] scratchPad) { + private KMAttestationCert makeSelfSignedCert(short attPrivKey, short attPubKey, short mode, + byte[] scratchPad) { KMAttestationCert cert = makeCommonCert(scratchPad); - short alg = KMKeyParameters.findTag(KMType.ENUM_TAG, KMType.ALGORITHM, data[KEY_PARAMETERS]); - byte mode = KMType.FAKE_CERT; - if(attPrivKey != KMType.INVALID_VALUE){ - mode = KMType.SELF_SIGNED_CERT; - } - short subject = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.CERTIFICATE_SUBJECT_NAME, data[KEY_PARAMETERS]); + // The Algorithm value can be read from either data[HW_PARAMETERS] or data[KEY_PARAMETERS] + // as the values will be same, and they are cryptographically bound. + short alg = KMEnumTag.getValue(KMType.ALGORITHM, data[HW_PARAMETERS]); + short subject = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.CERTIFICATE_SUBJECT_NAME, + data[KEY_PARAMETERS]); // If no subject name is specified then use the default subject name. - if(subject == KMType.INVALID_VALUE || KMByteTag.cast(subject).length() == 0){ + if (subject == KMType.INVALID_VALUE || KMByteTag.cast(subject).length() == 0) { subject = KMByteBlob.instance(defaultSubject, (short) 0, (short) defaultSubject.length); - }else{ + } else { subject = KMByteTag.cast(subject).getValue(); } - if(KMEnumTag.cast(alg).getValue() == KMType.RSA) { - cert.rsaAttestKey(attPrivKey, attPubKey, mode); - }else{ - cert.ecAttestKey(attPrivKey, mode); + if (KMEnumTag.cast(alg).getValue() == KMType.RSA) { + cert.rsaAttestKey(attPrivKey, attPubKey, (byte) mode); + } else { + cert.ecAttestKey(attPrivKey, (byte) mode); } cert.issuer(subject); cert.subjectName(subject); @@ -1484,34 +1463,29 @@ private static void addTags(short params, boolean hwEnforced, KMAttestationCert } } - private static void setUniqueId(KMAttestationCert cert, byte[] scratchPad) { - if(!KMTag.isPresent(data[KEY_PARAMETERS],KMType.BOOL_TAG, KMType.INCLUDE_UNIQUE_ID)){ + private static void setUniqueId(KMAttestationCert cert, short attAppId, byte[] scratchPad) { + if (!KMTag.isPresent(data[KEY_PARAMETERS], KMType.BOOL_TAG, KMType.INCLUDE_UNIQUE_ID)) { return; } // temporal count T - short time = KMKeyParameters.findTag(KMType.DATE_TAG, KMType.CREATION_DATETIME, data[KEY_PARAMETERS]); - if(time == KMType.INVALID_VALUE){ - KMException.throwIt(KMError.INVALID_TAG); + short time = KMKeyParameters.findTag(KMType.DATE_TAG, KMType.CREATION_DATETIME, + data[KEY_PARAMETERS]); + if (time == KMType.INVALID_VALUE) { + KMException.throwIt(KMError.INVALID_KEY_BLOB); } time = KMIntegerTag.cast(time).getValue(); - // Application Id C - short appId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.ATTESTATION_APPLICATION_ID, data[KEY_PARAMETERS]); - if (appId == KMType.INVALID_VALUE) { - KMException.throwIt(KMError.ATTESTATION_APPLICATION_ID_MISSING); - } - appId = KMByteTag.cast(appId).getValue(); - // Reset After Rotation R - it will be part of HW Enforced key // characteristics byte resetAfterRotation = 0; - if(KMTag.isPresent(data[KEY_PARAMETERS], KMType.BOOL_TAG, KMType.RESET_SINCE_ID_ROTATION)){ + if (KMTag.isPresent(data[KEY_PARAMETERS], KMType.BOOL_TAG, KMType.RESET_SINCE_ID_ROTATION)) { resetAfterRotation = 0x01; } cert.makeUniqueId(scratchPad, (short) 0, KMInteger.cast(time).getBuffer(), KMInteger.cast(time).getStartOff(), KMInteger.cast(time).length(), - KMByteBlob.cast(appId).getBuffer(), KMByteBlob.cast(appId).getStartOff(), KMByteBlob.cast(appId).length(), resetAfterRotation, + KMByteBlob.cast(attAppId).getBuffer(), KMByteBlob.cast(attAppId).getStartOff(), + KMByteBlob.cast(attAppId).length(), resetAfterRotation, kmDataStore.getMasterKey()); } @@ -2117,16 +2091,8 @@ private void processBeginOperationCmd(APDU apdu) { data[HW_TOKEN] = KMArray.cast(cmd).get((short) 3); purpose = KMEnum.cast(purpose).getVal(); // Check for app id and app data. - data[APP_ID] = - KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, data[KEY_PARAMETERS]); - data[APP_DATA] = - KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, data[KEY_PARAMETERS]); - if (data[APP_ID] != KMTag.INVALID_VALUE) { - data[APP_ID] = KMByteTag.cast(data[APP_ID]).getValue(); - } - if (data[APP_DATA] != KMTag.INVALID_VALUE) { - data[APP_DATA] = KMByteTag.cast(data[APP_DATA]).getValue(); - } + data[APP_ID] = getApplicationId(data[KEY_PARAMETERS]); + data[APP_DATA] = getApplicationData(data[KEY_PARAMETERS]); // Check if key requires upgrade. The KeyBlob is parsed inside isKeyUpgradeRequired // function itself. if (isKeyUpgradeRequired(data[KEY_BLOB], data[APP_ID], data[APP_DATA], scratchPad)) { @@ -3395,11 +3361,13 @@ private void processGenerateKey(APDU apdu) { byte[] scratchPad = apdu.getBuffer(); data[KEY_PARAMETERS] = KMArray.cast(cmd).get((short) 0); // ROLLBACK_RESISTANCE not supported. - KMTag.assertAbsence(data[KEY_PARAMETERS], KMType.BOOL_TAG,KMType.ROLLBACK_RESISTANCE, KMError.ROLLBACK_RESISTANCE_UNAVAILABLE); + KMTag.assertAbsence(data[KEY_PARAMETERS], KMType.BOOL_TAG,KMType.ROLLBACK_RESISTANCE, + KMError.ROLLBACK_RESISTANCE_UNAVAILABLE); // As per specification Early boot keys may be created after early boot ended. // Algorithm must be present - KMTag.assertPresence(data[KEY_PARAMETERS], KMType.ENUM_TAG, KMType.ALGORITHM, KMError.INVALID_ARGUMENT); + KMTag.assertPresence(data[KEY_PARAMETERS], KMType.ENUM_TAG, KMType.ALGORITHM, + KMError.INVALID_ARGUMENT); //Check if the tags are supported. if (KMKeyParameters.hasUnsupportedTags(data[KEY_PARAMETERS])) { @@ -3480,6 +3448,30 @@ public void getAttestKeyInputParameters(short arrPtr, short[] data, byte keyBlob data[attestKeyIssuerOff] = KMType.INVALID_VALUE; } + private short getApplicationId(short params) { + short appId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, params); + if (appId != KMTag.INVALID_VALUE) { + appId = KMByteTag.cast(appId).getValue(); + if (KMByteBlob.cast(appId).length() == 0) { + // Treat empty as INVALID. + return KMType.INVALID_VALUE; + } + } + return appId; + } + + private short getApplicationData(short params) { + short appData = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, params); + if (appData != KMTag.INVALID_VALUE) { + appData = KMByteTag.cast(appData).getValue(); + if (KMByteBlob.cast(appData).length() == 0) { + // Treat empty as INVALID. + return KMType.INVALID_VALUE; + } + } + return appData; + } + private void processAttestKeyCmd(APDU apdu) { // Receive the incoming request fully from the master into buffer. short cmd = generateAttestKeyCmd(apdu); @@ -3495,22 +3487,19 @@ private void processAttestKeyCmd(APDU apdu) { data[CERTIFICATE] = KMArray.instance((short) 0); // by default the cert is empty. // Check for app id and app data. - data[APP_ID] = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, data[KEY_PARAMETERS]); - data[APP_DATA] = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_DATA, data[KEY_PARAMETERS]); - if (data[APP_ID] != KMTag.INVALID_VALUE) { - data[APP_ID] = KMByteTag.cast(data[APP_ID]).getValue(); - } - if (data[APP_DATA] != KMTag.INVALID_VALUE) { - data[APP_DATA] = KMByteTag.cast(data[APP_DATA]).getValue(); - } + data[APP_ID] = getApplicationId(data[KEY_PARAMETERS]); + data[APP_DATA] = getApplicationData(data[KEY_PARAMETERS]); // Check if key requires upgrade. The KeyBlob is parsed inside isKeyUpgradeRequired // function itself. - parseEncryptedKeyBlob(data[KEY_BLOB], data[APP_ID], data[APP_DATA], scratchPad, KEYBLOB_CURRENT_VERSION); + parseEncryptedKeyBlob(data[KEY_BLOB], data[APP_ID], data[APP_DATA], scratchPad, + KEYBLOB_CURRENT_VERSION); // Validate KeyParams Mac if (!validateKeyParamsMac(data[KEY_PARAMETERS], keyParamsMac, scratchPad)) { KMException.throwIt(KMError.INVALID_KEY_BLOB); } // The key which is being attested should be asymmetric i.e. RSA or EC + // The Algorithm value can be read from either data[HW_PARAMETERS] or data[KEY_PARAMETERS] + // as the values will be same, and they are cryptographically bound. short alg = KMEnumTag.getValue(KMType.ALGORITHM, data[HW_PARAMETERS]); if (alg == KMType.RSA || alg == KMType.EC) { // Build certificate @@ -3522,13 +3511,8 @@ private void processAttestKeyCmd(APDU apdu) { sendOutgoing(apdu, resp); } - private short getAttestationMode(short attKeyBlob, short attChallenge){ - short alg = KMKeyParameters.findTag(KMType.ENUM_TAG, KMType.ALGORITHM, data[KEY_PARAMETERS]); + private short getAttestationMode(short attKeyBlob, short attChallenge) { short mode = KMType.NO_CERT; - if(KMEnumTag.cast(alg).getValue() != KMType.RSA && - KMEnumTag.cast(alg).getValue() != KMType.EC){ - return mode; - } // If attestation keyblob preset if (attKeyBlob != KMType.INVALID_VALUE && KMByteBlob.cast(attKeyBlob).length() > 0) { // No attestation challenge present then it is an error @@ -3537,14 +3521,16 @@ private short getAttestationMode(short attKeyBlob, short attChallenge){ } else { mode = KMType.ATTESTATION_CERT; } - }else{ // no attestation key blob + } else { // no attestation key blob // Attestation challenge present then it is an error because no factory provisioned attest key if (attChallenge != KMType.INVALID_VALUE && KMByteBlob.cast(attChallenge).length() > 0) { KMException.throwIt(KMError.ATTESTATION_KEYS_NOT_PROVISIONED); - } else if(KMEnumArrayTag.contains(KMType.PURPOSE, KMType.ATTEST_KEY, data[KEY_PARAMETERS]) || - KMEnumArrayTag.contains(KMType.PURPOSE, KMType.SIGN, data[KEY_PARAMETERS])) { + } else if (KMEnumArrayTag.contains(KMType.PURPOSE, KMType.ATTEST_KEY, data[HW_PARAMETERS]) || + KMEnumArrayTag.contains(KMType.PURPOSE, KMType.SIGN, data[HW_PARAMETERS])) { + // The Purpose value can be read from either data[HW_PARAMETERS] or data[KEY_PARAMETERS] + // as the values will be same, and they are cryptographically bound. mode = KMType.SELF_SIGNED_CERT; - }else{ + } else { mode = KMType.FAKE_CERT; } } @@ -3553,11 +3539,12 @@ private short getAttestationMode(short attKeyBlob, short attChallenge){ private void generateAttestation(short attKeyBlob, short attKeyParam, byte[] scratchPad){ // Device unique attestation not supported - KMTag.assertAbsence(data[KEY_PARAMETERS],KMType.BOOL_TAG,KMType.DEVICE_UNIQUE_ATTESTATION,KMError.CANNOT_ATTEST_IDS); + KMTag.assertAbsence(data[KEY_PARAMETERS], KMType.BOOL_TAG, KMType.DEVICE_UNIQUE_ATTESTATION, + KMError.CANNOT_ATTEST_IDS); // Read attestation challenge if present short attChallenge = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.ATTESTATION_CHALLENGE, data[KEY_PARAMETERS]); - if(attChallenge != KMType.INVALID_VALUE){ + if(attChallenge != KMType.INVALID_VALUE) { attChallenge = KMByteTag.cast(attChallenge).getValue(); } // No attestation required for symmetric keys @@ -3566,16 +3553,14 @@ private void generateAttestation(short attKeyBlob, short attKeyParam, byte[] sc switch (mode){ case KMType.ATTESTATION_CERT: - cert = makeAttestationCert(attKeyBlob, attKeyParam, attChallenge, data[ATTEST_KEY_ISSUER],data[HW_PARAMETERS], - data[SW_PARAMETERS], scratchPad); + cert = makeAttestationCert(attKeyBlob, attKeyParam, attChallenge, data[ATTEST_KEY_ISSUER], + data[HW_PARAMETERS], scratchPad); break; case KMType.SELF_SIGNED_CERT: - //cert = makeCert(attKeyBlob, attKeyParam, scratchPad); - cert = makeSelfSignedCert(data[SECRET], data[PUB_KEY],scratchPad); + cert = makeSelfSignedCert(data[SECRET], data[PUB_KEY], mode, scratchPad); break; case KMType.FAKE_CERT: - //cert = makeCert(attKeyBlob, attKeyParam, scratchPad); - cert = makeSelfSignedCert(KMType.INVALID_VALUE, data[PUB_KEY], scratchPad); + cert = makeSelfSignedCert(KMType.INVALID_VALUE, data[PUB_KEY], mode, scratchPad); break; default: data[CERTIFICATE] = KMArray.instance((short)0); @@ -3680,7 +3665,7 @@ private static void generateAESKey(byte[] scratchPad) { private static void validateECKeys() { // Read key size short eccurve = KMEnumTag.getValue(KMType.ECCURVE, data[KEY_PARAMETERS]); - if(!KMTag.isValidKeySize(data[KEY_PARAMETERS])){ + if(!KMTag.isValidKeySize(data[KEY_PARAMETERS])) { if (eccurve == KMType.INVALID_VALUE) { KMException.throwIt(KMError.UNSUPPORTED_KEY_SIZE); } else if (eccurve != KMType.P_256) { diff --git a/Applet/src/com/android/javacard/keymaster/KMType.java b/Applet/src/com/android/javacard/keymaster/KMType.java index 7aab6c7d..df78ba4e 100644 --- a/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/Applet/src/com/android/javacard/keymaster/KMType.java @@ -358,6 +358,14 @@ public abstract class KMType { public static final byte BUF_DES_DECRYPT_PKCS7_BLOCK_ALIGN = 6; public static final byte BUF_AES_GCM_DECRYPT_BLOCK_ALIGN = 7; + // 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; + // Max certificate serial size. + public static final short MAX_CERTIFICATE_SERIAL_SIZE = 20; + + protected static KMRepository repository; protected static byte[] heap; // Instance table From 3b55e2da6e046f429ecd367562c8e1aee8703733 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Tue, 12 Apr 2022 19:17:46 +0000 Subject: [PATCH 4/6] Fixed compilation erros --- Applet/src/com/android/javacard/keymaster/KMByteTag.java | 2 +- .../src/com/android/javacard/keymaster/KMKeymasterApplet.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMByteTag.java b/Applet/src/com/android/javacard/keymaster/KMByteTag.java index e33cc4db..b7b8decd 100644 --- a/Applet/src/com/android/javacard/keymaster/KMByteTag.java +++ b/Applet/src/com/android/javacard/keymaster/KMByteTag.java @@ -130,6 +130,6 @@ private static boolean validateKey(short key, short byteBlob) { default: return false; } - return result; + return true; } } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 0eb32fe0..5171abde 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -1376,7 +1376,7 @@ private KMAttestationCert makeSelfSignedCert(short attPrivKey, short attPubKey, subject = KMByteTag.cast(subject).getValue(); } - if (KMEnumTag.cast(alg).getValue() == KMType.RSA) { + if (alg == KMType.RSA) { cert.rsaAttestKey(attPrivKey, attPubKey, (byte) mode); } else { cert.ecAttestKey(attPrivKey, (byte) mode); From 7a3760c4f463b0e49a4bb2d9d09638f7c23e8ee3 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Tue, 12 Apr 2022 22:14:26 +0000 Subject: [PATCH 5/6] Addressed review comments --- .../android/javacard/keymaster/KMEncoder.java | 4 +-- .../javacard/keymaster/KMKeymasterApplet.java | 6 ++-- HAL/JavacardKeyMintDevice.cpp | 35 +++++++++++++++---- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMEncoder.java b/Applet/src/com/android/javacard/keymaster/KMEncoder.java index 0ba1986c..e47d799d 100644 --- a/Applet/src/com/android/javacard/keymaster/KMEncoder.java +++ b/Applet/src/com/android/javacard/keymaster/KMEncoder.java @@ -82,8 +82,8 @@ public short encode(short object, byte[] buffer, short startOff) { bufferRef[0] = buffer; scratchBuf[START_OFFSET] = startOff; short len = (short) (buffer.length - startOff); - if ((len < 0) || len > KMKeymasterApplet.MAX_LENGTH) { - scratchBuf[LEN_OFFSET] = KMKeymasterApplet.MAX_LENGTH; + if ((len < 0) || len > KMRepository.HEAP_SIZE) { + scratchBuf[LEN_OFFSET] = KMRepository.HEAP_SIZE; } else { scratchBuf[LEN_OFFSET] = (short) buffer.length; } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 5171abde..66423fb9 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -44,7 +44,6 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe public static final byte[] F4 = {0x01, 0x00, 0x01}; public static final byte AES_BLOCK_SIZE = 16; public static final byte DES_BLOCK_SIZE = 8; - public static final short MAX_LENGTH = 10000; public static final short MASTER_KEY_SIZE = 128; public static final short WRAPPING_KEY_SIZE = 32; public static final short MAX_OPERATIONS_COUNT = 4; @@ -3491,8 +3490,9 @@ private void processAttestKeyCmd(APDU apdu) { data[APP_DATA] = getApplicationData(data[KEY_PARAMETERS]); // Check if key requires upgrade. The KeyBlob is parsed inside isKeyUpgradeRequired // function itself. - parseEncryptedKeyBlob(data[KEY_BLOB], data[APP_ID], data[APP_DATA], scratchPad, - KEYBLOB_CURRENT_VERSION); + if (isKeyUpgradeRequired(data[KEY_BLOB], data[APP_ID], data[APP_DATA], scratchPad)) { + KMException.throwIt(KMError.KEY_REQUIRES_UPGRADE); + } // Validate KeyParams Mac if (!validateKeyParamsMac(data[KEY_PARAMETERS], keyParamsMac, scratchPad)) { KMException.throwIt(KMError.INVALID_KEY_BLOB); diff --git a/HAL/JavacardKeyMintDevice.cpp b/HAL/JavacardKeyMintDevice.cpp index 0cb1bec6..ae78079b 100644 --- a/HAL/JavacardKeyMintDevice.cpp +++ b/HAL/JavacardKeyMintDevice.cpp @@ -93,7 +93,7 @@ ScopedAStatus JavacardKeyMintDevice::generateKey(const vector& key // Call attestKey only Asymmetric algorithms. keymaster_algorithm_t algorithm; paramSet.GetTagValue(TAG_ALGORITHM, &algorithm); - if (algorithm == KM_ALGORITHM_RSA || algorithm == KM_ALGORITHM_EC) { + if (algorithm == KM_ALGORITHM_RSA || algorithm == KM_ALGORITHM_EC) { cppbor::Array attestKeyArray; attestKeyArray.add(creationResult->keyBlob); cbor_.addKeyparameters(attestKeyArray, keyParams); @@ -101,12 +101,19 @@ ScopedAStatus JavacardKeyMintDevice::generateKey(const vector& key attestKeyArray.add(keyParamsMac); auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); if (error != KM_ERROR_OK) { - LOG(ERROR) << "Failed in attestKey err: "; - return km_utils::kmError2ScopedAStatus(error); + LOG(ERROR) << "Failed in attestKey err: " << error; + if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) { + // This is rare scenario where either the applet gets upgraded or system propeties + // like osVersion, OsPatch, VendorPatch and bootPatches values changes. + LOG(DEBUG) << "This error occurs in case if either the applets get upgraded or if any" + "system properties like OsVersion, OsPatch, VendorPatch or bootPatch values changes"; + error = KM_ERROR_UNKNOWN_ERROR; + } + return km_utils::kmError2ScopedAStatus(error); } if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) { - LOG(ERROR) << "Error in decoding og response in generateKey."; - return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); + LOG(ERROR) << "Error in decoding og response in generateKey."; + return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR); } } return ScopedAStatus::ok(); @@ -163,7 +170,14 @@ ScopedAStatus JavacardKeyMintDevice::importKey(const vector& keyPa attestKeyArray.add(keyParamsMac); auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); if (error != KM_ERROR_OK) { - LOG(ERROR) << "Failed in attestKey err: "; + LOG(ERROR) << "Failed in attestKey err: " << error; + if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) { + // This is rare scenario where either the applet gets upgraded or system propeties + // like osVersion, OsPatch, VendorPatch and bootPatches values changes. + LOG(DEBUG) << "This error occurs in case if either the applets get upgraded or if any" + "system properties like OsVersion, OsPatch, VendorPatch or bootPatch values changes"; + error = KM_ERROR_UNKNOWN_ERROR; + } return km_utils::kmError2ScopedAStatus(error); } if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) { @@ -235,7 +249,14 @@ ScopedAStatus JavacardKeyMintDevice::importWrappedKey(const vector& wra cbor_.addAttestationKey(attestKeyArray, std::nullopt); auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); if (error != KM_ERROR_OK) { - LOG(ERROR) << "Failed in attestKey err: "; + LOG(ERROR) << "Failed in attestKey err: " << error; + if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) { + // This is rare scenario where either the applet gets upgraded or system propeties + // like osVersion, OsPatch, VendorPatch and bootPatches values changes. + LOG(DEBUG) << "This error occurs in case if either the applets get upgraded or if any" + "system properties like OsVersion, OsPatch, VendorPatch or bootPatch values changes"; + error = KM_ERROR_UNKNOWN_ERROR; + } return km_utils::kmError2ScopedAStatus(error); } if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) { From 2e36786bc3fd2ec7fb7a489d44daefb0d1d74ed7 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Wed, 13 Apr 2022 03:00:26 +0000 Subject: [PATCH 6/6] 1. In processAttestKey , call isKeyUpgradeRequired() for generated key also and return KEY_REQUIRES_UPGRADE error if upgrade condition passes. 2. using reclaimable buffer for encoding the key_paramters while creating mac for keyparamters. if the encoded key_paramters length exceeds 3K return INSUFFICIENT_BUFFER_SPACE error. 3. HAL does not handle KEY_REQUIRES_UPGRADE error. --- .../android/javacard/keymaster/KMError.java | 1 + .../javacard/keymaster/KMKeymasterApplet.java | 27 ++++++++++++++----- HAL/JavacardKeyMintDevice.cpp | 21 --------------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMError.java b/Applet/src/com/android/javacard/keymaster/KMError.java index 52398824..5e93b49b 100644 --- a/Applet/src/com/android/javacard/keymaster/KMError.java +++ b/Applet/src/com/android/javacard/keymaster/KMError.java @@ -45,6 +45,7 @@ public class KMError { public static final short KEY_USER_NOT_AUTHENTICATED = 26; public static final short INVALID_OPERATION_HANDLE = 28; + public static final short INSUFFICIENT_BUFFER_SPACE = 29; public static final short VERIFICATION_FAILED = 30; public static final short TOO_MANY_OPERATIONS = 31; public static final short INVALID_KEY_BLOB = 33; diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 66423fb9..6a250d3c 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -108,8 +108,9 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe }; public static final short MAX_COSE_BUF_SIZE = (short) 1024; - // Maximum possible encoded keyparams size - public static final short MAX_KEY_PARAMS_BUF_SIZE = (short) 2048; + // Maximum allowed buffer size for to encode the key parameters + // which is used while creating mac for key paramters. + public static final short MAX_KEY_PARAMS_BUF_SIZE = (short) 3072; // 3K // Top 32 commands are reserved for provisioning. private static final byte KEYMINT_CMD_APDU_START = 0x20; @@ -3491,6 +3492,10 @@ private void processAttestKeyCmd(APDU apdu) { // Check if key requires upgrade. The KeyBlob is parsed inside isKeyUpgradeRequired // function itself. if (isKeyUpgradeRequired(data[KEY_BLOB], data[APP_ID], data[APP_DATA], scratchPad)) { + // This condition occurs if either any of the system properties (OsVersion, OsPatchLevel, + // VendorPatchLevel or BootPatchLevel) changes or KeyBlob format changed. So return + // KEY_REQUIRES_UPGRADE error as this scenario is application to ATTEST_KEY_BLOB as well + // as ATTEST_KEY_BLOB got generated before the KEY_BLOB. KMException.throwIt(KMError.KEY_REQUIRES_UPGRADE); } // Validate KeyParams Mac @@ -3786,18 +3791,26 @@ private short macKeyParams(short keyParams, byte[] scratchPad) { if (SYM_KEY_TYPE == getKeyType(keyParams)) { return KMByteBlob.instance((short) 0); } - short len = encodeToApduBuffer(keyParams, scratchPad, (short) 0, MAX_KEY_PARAMS_BUF_SIZE); + short offset = repository.allocReclaimableMemory(MAX_KEY_PARAMS_BUF_SIZE); + short len = encoder.encode(keyParams, repository.getHeap(), offset); + if (len > MAX_KEY_PARAMS_BUF_SIZE) { + // KeyParamters exceeded the maximum allowed size. + KMException.throwIt(KMError.INSUFFICIENT_BUFFER_SPACE); + } short signLen = seProvider.hmacSign( KMByteBlob.cast(data[AUTH_TAG]).getBuffer(), KMByteBlob.cast(data[AUTH_TAG]).getStartOff(), KMByteBlob.cast(data[AUTH_TAG]).length(), - scratchPad, - (short) 0, + repository.getHeap(), + offset, len, scratchPad, - len); - return KMByteBlob.instance(scratchPad, len, signLen); + (short) 0); + //release memory + repository.reclaimMemory(MAX_KEY_PARAMS_BUF_SIZE); + + return KMByteBlob.instance(scratchPad, (short) 0, signLen); } private boolean validateKeyParamsMac(short keyParams, short keyParamsMac, byte[] scratchPad) { diff --git a/HAL/JavacardKeyMintDevice.cpp b/HAL/JavacardKeyMintDevice.cpp index ae78079b..03a1b004 100644 --- a/HAL/JavacardKeyMintDevice.cpp +++ b/HAL/JavacardKeyMintDevice.cpp @@ -102,13 +102,6 @@ ScopedAStatus JavacardKeyMintDevice::generateKey(const vector& key auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); if (error != KM_ERROR_OK) { LOG(ERROR) << "Failed in attestKey err: " << error; - if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) { - // This is rare scenario where either the applet gets upgraded or system propeties - // like osVersion, OsPatch, VendorPatch and bootPatches values changes. - LOG(DEBUG) << "This error occurs in case if either the applets get upgraded or if any" - "system properties like OsVersion, OsPatch, VendorPatch or bootPatch values changes"; - error = KM_ERROR_UNKNOWN_ERROR; - } return km_utils::kmError2ScopedAStatus(error); } if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) { @@ -171,13 +164,6 @@ ScopedAStatus JavacardKeyMintDevice::importKey(const vector& keyPa auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); if (error != KM_ERROR_OK) { LOG(ERROR) << "Failed in attestKey err: " << error; - if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) { - // This is rare scenario where either the applet gets upgraded or system propeties - // like osVersion, OsPatch, VendorPatch and bootPatches values changes. - LOG(DEBUG) << "This error occurs in case if either the applets get upgraded or if any" - "system properties like OsVersion, OsPatch, VendorPatch or bootPatch values changes"; - error = KM_ERROR_UNKNOWN_ERROR; - } return km_utils::kmError2ScopedAStatus(error); } if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) { @@ -250,13 +236,6 @@ ScopedAStatus JavacardKeyMintDevice::importWrappedKey(const vector& wra auto [certItem, error] = card_->sendRequest(Instruction::INS_ATTEST_KEY_CMD, attestKeyArray); if (error != KM_ERROR_OK) { LOG(ERROR) << "Failed in attestKey err: " << error; - if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) { - // This is rare scenario where either the applet gets upgraded or system propeties - // like osVersion, OsPatch, VendorPatch and bootPatches values changes. - LOG(DEBUG) << "This error occurs in case if either the applets get upgraded or if any" - "system properties like OsVersion, OsPatch, VendorPatch or bootPatch values changes"; - error = KM_ERROR_UNKNOWN_ERROR; - } return km_utils::kmError2ScopedAStatus(error); } if (!cbor_.getCertificateChain(certItem, 1, creationResult->certificateChain)) {