From 56e18795344ecc22a9c75b7590523d2ff9448443 Mon Sep 17 00:00:00 2001 From: Prashant Patil Date: Fri, 29 May 2020 18:55:28 +0530 Subject: [PATCH 1/8] Error handling while import key is corrected and started changes for verification operation in begin function --- .../4.1/JavacardKeymaster4Device.cpp | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index 98b81074..fa7912b2 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -69,6 +69,10 @@ inline ErrorCode legacy_enum_conversion(const keymaster_error_t value) { return static_cast(value); } +inline keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) { + return static_cast(value); +} + inline keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) { return static_cast(value); } @@ -376,7 +380,7 @@ Return JavacardKeymaster4Device::generateKey(const hidl_vec& } Return JavacardKeymaster4Device::importKey(const hidl_vec& keyParams, KeyFormat keyFormat, const hidl_vec& keyData, importKey_cb _hidl_cb) { - keymaster_error_t error; + keymaster_error_t error = KM_ERROR_UNKNOWN_ERROR; hidl_vec inKey; if (keyFormat == KeyFormat::PKCS8) { @@ -390,6 +394,7 @@ Return JavacardKeymaster4Device::importKey(const hidl_vec& k KeyCharacteristics resultCharacteristics; hidl_vec resultKeyBlob; + error = response.error; if (response.error == KM_ERROR_OK) { AuthorizationSet hidden; error = BuildHiddenAuthorizations(request.key_description, &hidden, softwareRootOfTrust); @@ -400,6 +405,12 @@ Return JavacardKeymaster4Device::importKey(const hidl_vec& k inKey.setToExternal(const_cast(key_material.key_material), key_material.key_material_size); } } + if(error != KM_ERROR_OK) { + KeyCharacteristics resultCharacteristics; + hidl_vec resultKeyBlob; + _hidl_cb(legacy_enum_conversion(error), resultKeyBlob, resultCharacteristics); + return Void(); + } } else if (keyFormat == KeyFormat::RAW) { //convert keyData to keyMaterial inKey = keyData; @@ -418,7 +429,7 @@ Return JavacardKeymaster4Device::importKey(const hidl_vec& k KeyCharacteristics keyCharacteristics; cborConverter_.addKeyparameters(array, keyParams); - array.add(static_cast(keyFormat)); + array.add(static_cast(KeyFormat::RAW)); //PKCS8 is already converted to RAW array.add(std::vector(inKey)); std::vector cborData = array.encode(); @@ -629,8 +640,26 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< hidl_vec outParams; uint64_t operationHandle = 0; - if (KeyPurpose::ENCRYPT == purpose || - KeyPurpose::VERIFY == purpose) { + if (/*KeyPurpose::ENCRYPT == purpose ||*/ KeyPurpose::VERIFY == purpose) { + + BeginOperationRequest request; + request.purpose = legacy_enum_conversion(purpose); + request.SetKeyMaterial(keyBlob.data(), keyBlob.size()); + request.additional_params.Reinitialize(KmParamSet(inParams)); + + //TODO need to check AUTH_TOKEN will work here? + //hidl_vec hidl_vec_token = authToken2HidlVec(authToken); + //request.additional_params.push_back( + // TAG_AUTH_TOKEN, reinterpret_cast(hidl_vec_token.data()), hidl_vec_token.size()); + + BeginOperationResponse response; + softKm_->BeginOperation(request, &response); + + //hidl_vec resultParams; + //if (response.error == KM_ERROR_OK) resultParams = kmParamSet2Hidl(response.output_params); + + //_hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle); + return Void(); /* Public key operations are handled here*/ } else { cppbor::Array array; From fc69e0d26536308e537797173d0246464612d7aa Mon Sep 17 00:00:00 2001 From: BKSSM Venkateswarlu Date: Fri, 5 Jun 2020 16:57:00 +0530 Subject: [PATCH 2/8] Added setBootParams method. Calling it first time before any API gets called. --- .../4.1/JavacardKeymaster4Device.cpp | 105 ++++++++++++------ .../include/JavacardKeymaster4Device.h | 5 + 2 files changed, 78 insertions(+), 32 deletions(-) diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index 98b81074..9c2e4e5b 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -61,8 +62,9 @@ enum class Instruction { INS_FINISH_OPERATION_CMD = 0x21, INS_ABORT_OPERATION_CMD = 0x22, INS_PROVISION_CMD = 0x23, - INS_DEVICE_LOCKED_CMD = 0x24, - INS_EARLY_BOOT_ENDED_CMD = 0x25 + INS_SET_BOOT_PARAMS_CMD = 0x24, + INS_DEVICE_LOCKED_CMD = 0x25, + INS_EARLY_BOOT_ENDED_CMD = 0x26, }; inline ErrorCode legacy_enum_conversion(const keymaster_error_t value) { @@ -149,10 +151,10 @@ JavacardKeymaster4Device::JavacardKeymaster4Device(): softKm_(new ::keymaster::A context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel()); return context; }(), - kOperationTableSize)) { + kOperationTableSize)), setUpBootParams(false) { pTransportFactory = std::unique_ptr(new se_transport::TransportFactory( android::base::GetBoolProperty("ro.kernel.qemu", false))); - assert(pTransportFactory->openConnection() && "Failed to open connection with secure element"); + pTransportFactory->openConnection(); } JavacardKeymaster4Device::~JavacardKeymaster4Device() {} @@ -195,15 +197,53 @@ uint16_t getStatus(std::vector& inputData) { return (inputData.at(inputData.size()-2) << 8) | (inputData.at(inputData.size()-1)); } -inline ErrorCode sendData(std::unique_ptr& transport, Instruction ins, std::vector& inData, -std::vector& response) { +/* This method should be called at the time when HAL is initialized for the first time */ +Return setBootParams(std::unique_ptr& transport) { + cppbor::Array array; std::vector apdu; - ErrorCode ret = constructApduMessage(ins, inData, apdu); + std::vector response; + Instruction ins = Instruction::INS_SET_BOOT_PARAMS_CMD; + std::vector verifiedBootKey(32, 0); + std::vector verifiedBootKeyHash(32, 0); + array.add(GetOsVersion()). + add(GetOsPatchlevel()). + /* Verified Boot Key */ + add(verifiedBootKey). + /* Verified Boot Hash */ + add(verifiedBootKeyHash). + /* boot state */ + add(static_cast(KM_VERIFIED_BOOT_UNVERIFIED)). + /* device locked */ + add(0); /* false */ + std::vector cborData = array.encode(); + + ErrorCode ret = constructApduMessage(ins, cborData, apdu); if(ret != ErrorCode::OK) return ret; - //if(!transport->openConnection()) { - // return (ErrorCode::SECURE_HW_COMMUNICATION_FAILED); - //} + if(!transport->sendData(apdu.data(), apdu.size(), response)) { + return (ErrorCode::SECURE_HW_COMMUNICATION_FAILED); + } + + if((response.size() < 2) || (getStatus(response) != APDU_RESP_STATUS_OK)) { + return (ErrorCode::UNKNOWN_ERROR); + } + return ErrorCode::OK; +} + +ErrorCode sendData(JavacardKeymaster4Device *pKeymaster, std::unique_ptr& transport, Instruction ins, std::vector& inData, +std::vector& response) { + ErrorCode ret = ErrorCode::UNKNOWN_ERROR; + std::vector apdu; + + if(!pKeymaster->getBootParamsInitialized()) { + if((ret = setBootParams(transport)) != ErrorCode::OK) { + return ret; + } + pKeymaster->setBootParams(true); + } + + ret = constructApduMessage(ins, inData, apdu); + if(ret != ErrorCode::OK) return ret; if(!transport->sendData(apdu.data(), apdu.size(), response)) { return (ErrorCode::SECURE_HW_COMMUNICATION_FAILED); @@ -225,7 +265,7 @@ Return JavacardKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_ hidl_string jcKeymasterName; hidl_string jcKeymasterAuthor; - ErrorCode ret = sendData(pTransportFactory, Instruction::INS_GET_HW_INFO_CMD, input, resp); + ErrorCode ret = sendData(this, pTransportFactory, Instruction::INS_GET_HW_INFO_CMD, input, resp); if((ret == ErrorCode::OK) && (resp.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -252,7 +292,7 @@ Return JavacardKeymaster4Device::getHmacSharingParameters(getHmacSharingPa HmacSharingParameters hmacSharingParameters; ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; - errorCode = sendData(pTransportFactory, Instruction::INS_GET_HMAC_SHARING_PARAM_CMD, input, cborData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_GET_HMAC_SHARING_PARAM_CMD, input, cborData); if((errorCode == ErrorCode::OK) && (cborData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -286,7 +326,7 @@ Return JavacardKeymaster4Device::computeSharedHmac(const hidl_vec cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_COMPUTE_SHARED_HMAC_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_COMPUTE_SHARED_HMAC_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -315,7 +355,7 @@ Return JavacardKeymaster4Device::verifyAuthorization(uint64_t operationHan cborConverter_.addHardwareAuthToken(array, authToken); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_VERIFY_AUTHORIZATION_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_VERIFY_AUTHORIZATION_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -339,7 +379,7 @@ Return JavacardKeymaster4Device::addRngEntropy(const hidl_vec(data)); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_ADD_RNG_ENTROPY_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_ADD_RNG_ENTROPY_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -357,10 +397,11 @@ Return JavacardKeymaster4Device::generateKey(const hidl_vec& ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; KeyCharacteristics keyCharacteristics; + /* Convert to cbor format */ cborConverter_.addKeyparameters(array, keyParams); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_GENERATE_KEY_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_GENERATE_KEY_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -377,6 +418,7 @@ Return JavacardKeymaster4Device::generateKey(const hidl_vec& Return JavacardKeymaster4Device::importKey(const hidl_vec& keyParams, KeyFormat keyFormat, const hidl_vec& keyData, importKey_cb _hidl_cb) { keymaster_error_t error; + KeymasterKeyBlob key_material; hidl_vec inKey; if (keyFormat == KeyFormat::PKCS8) { @@ -394,7 +436,6 @@ Return JavacardKeymaster4Device::importKey(const hidl_vec& k AuthorizationSet hidden; error = BuildHiddenAuthorizations(request.key_description, &hidden, softwareRootOfTrust); if (error == KM_ERROR_OK) { - KeymasterKeyBlob key_material; DeserializeIntegrityAssuredBlob(KeymasterKeyBlob(response.key_blob), hidden, &key_material, &response.enforced, &response.unenforced); inKey.setToExternal(const_cast(key_material.key_material), key_material.key_material_size); @@ -422,7 +463,7 @@ Return JavacardKeymaster4Device::importKey(const hidl_vec& k array.add(std::vector(inKey)); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_IMPORT_KEY_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_IMPORT_KEY_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -453,7 +494,7 @@ Return JavacardKeymaster4Device::importWrappedKey(const hidl_vec& array.add(biometricSid); /* TODO if biometricSid optional if user not sent this don't encode this cbor format */ std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_IMPORT_WRAPPED_KEY_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_IMPORT_WRAPPED_KEY_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -481,7 +522,7 @@ Return JavacardKeymaster4Device::getKeyCharacteristics(const hidl_vec(appData)); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_GET_KEY_CHARACTERISTICS_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_GET_KEY_CHARACTERISTICS_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -508,7 +549,7 @@ Return JavacardKeymaster4Device::exportKey(KeyFormat keyFormat, const hidl array.add(std::vector(appData)); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_EXPORT_KEY_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_EXPORT_KEY_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -534,7 +575,7 @@ Return JavacardKeymaster4Device::attestKey(const hidl_vec& keyToA cborConverter_.addKeyparameters(array, attestParams); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_ATTEST_KEY_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_ATTEST_KEY_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -559,7 +600,7 @@ Return JavacardKeymaster4Device::upgradeKey(const hidl_vec& keyBl cborConverter_.addKeyparameters(array, upgradeParams); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_UPGRADE_KEY_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_UPGRADE_KEY_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -582,7 +623,7 @@ Return JavacardKeymaster4Device::deleteKey(const hidl_vec& k array.add(std::vector(keyBlob)); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_DELETE_KEY_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_DELETE_KEY_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -598,7 +639,7 @@ Return JavacardKeymaster4Device::deleteAllKeys() { std::vector input; ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; - errorCode = sendData(pTransportFactory, Instruction::INS_DELETE_ALL_KEYS_CMD, input, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_DELETE_ALL_KEYS_CMD, input, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -614,7 +655,7 @@ Return JavacardKeymaster4Device::destroyAttestationIds() { std::vector input; ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; - errorCode = sendData(pTransportFactory, Instruction::INS_DESTROY_ATT_IDS_CMD, input, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_DESTROY_ATT_IDS_CMD, input, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -644,7 +685,7 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< cborConverter_.addHardwareAuthToken(array, authToken); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_BEGIN_OPERATION_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_BEGIN_OPERATION_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -677,7 +718,7 @@ Return JavacardKeymaster4Device::update(uint64_t operationHandle, const hi cborConverter_.addVerificationToken(array, verificationToken); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_UPDATE_OPERATION_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_UPDATE_OPERATION_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -710,7 +751,7 @@ Return JavacardKeymaster4Device::finish(uint64_t operationHandle, const hi cborConverter_.addVerificationToken(array, verificationToken); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_FINISH_OPERATION_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_FINISH_OPERATION_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -735,7 +776,7 @@ Return JavacardKeymaster4Device::abort(uint64_t operationHandle) { array.add(operationHandle); std::vector cborData = array.encode(); - errorCode = sendData(pTransportFactory, Instruction::INS_ABORT_OPERATION_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_ABORT_OPERATION_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -758,7 +799,7 @@ Return<::android::hardware::keymaster::V4_1::ErrorCode> JavacardKeymaster4Device std::vector cborData = array.encode(); /* TODO DeviceLocked command handled inside HAL */ - ErrorCode ret = sendData(pTransportFactory, Instruction::INS_DEVICE_LOCKED_CMD, cborData, cborOutData); + ErrorCode ret = sendData(this, pTransportFactory, Instruction::INS_DEVICE_LOCKED_CMD, cborData, cborOutData); if((ret == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -775,7 +816,7 @@ Return<::android::hardware::keymaster::V4_1::ErrorCode> JavacardKeymaster4Device std::vector cborInput; ::android::hardware::keymaster::V4_1::ErrorCode errorCode = ::android::hardware::keymaster::V4_1::ErrorCode::UNKNOWN_ERROR; - ErrorCode ret = sendData(pTransportFactory, Instruction::INS_EARLY_BOOT_ENDED_CMD, cborInput, cborOutData); + ErrorCode ret = sendData(this, pTransportFactory, Instruction::INS_EARLY_BOOT_ENDED_CMD, cborInput, cborOutData); if((ret == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. diff --git a/HAL/keymaster/include/JavacardKeymaster4Device.h b/HAL/keymaster/include/JavacardKeymaster4Device.h index 058812e9..6d0be552 100644 --- a/HAL/keymaster/include/JavacardKeymaster4Device.h +++ b/HAL/keymaster/include/JavacardKeymaster4Device.h @@ -84,12 +84,17 @@ class JavacardKeymaster4Device : public IKeymasterDevice { Return deviceLocked(bool passwordOnly, const VerificationToken& verificationToken) override; Return earlyBootEnded() override; + //Helper methods. + bool getBootParamsInitialized() { return setUpBootParams; } + void setBootParams(bool flag) { setUpBootParams = flag; } + protected: CborConverter cborConverter_; std::unique_ptr pTransportFactory; private: std::unique_ptr<::keymaster::AndroidKeymaster> softKm_; + bool setUpBootParams; }; } // namespace javacard From 60351ae4b580fb51e5b83cb866f1a2615a6f4562 Mon Sep 17 00:00:00 2001 From: BKSSM Venkateswarlu Date: Sat, 13 Jun 2020 03:52:19 +0530 Subject: [PATCH 3/8] Added Operation context class --- .../4.1/JavacardOperationContext.cpp | 197 ++++++++++++++++++ HAL/keymaster/Android.bp | 1 + .../include/JavacardOperationContext.h | 80 +++++++ 3 files changed, 278 insertions(+) create mode 100644 HAL/keymaster/4.1/JavacardOperationContext.cpp create mode 100644 HAL/keymaster/include/JavacardOperationContext.h diff --git a/HAL/keymaster/4.1/JavacardOperationContext.cpp b/HAL/keymaster/4.1/JavacardOperationContext.cpp new file mode 100644 index 00000000..096ace36 --- /dev/null +++ b/HAL/keymaster/4.1/JavacardOperationContext.cpp @@ -0,0 +1,197 @@ +/* + ** + ** Copyright 2020, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#include + +#define MAX_ALLOWED_INPUT_SIZE 512 +#define AES_BLOCK_SIZE 16 +#define DES_BLOCK_SIZE 8 + +namespace keymaster { +namespace V4_1 { +namespace javacard { + +enum class Operation { + Update = 0, + Finish = 1 +}; + +struct BufferedData { + uint8_t buf[MAX_BUF_SIZE]; + int buf_len; +}; + +struct OperationData { + OperationInfo info; + BufferedData data; +}; + + +ErrorCode OperationContext::setOperationData(uint64_t operationHandle, OperationInfo& operInfo) { + OperationData data; + data.info = operInfo; + operationTable[operationHandle] = data; + return ErrorCode::OK; +} + +ErrorCode OperationContext::getOperationData(uint64_t operHandle, OperationInfo& operInfo) { + auto itr = operationTable.find(operHandle); + if(itr != operationTable.end()) { + operInfo = itr->second.info; + return ErrorCode::OK; + } + return ErrorCode::INVALID_OPERATION_HANDLE; +} + +ErrorCode OperationContext::clearOperationData(uint64_t operHandle) { + size_t size = operationTable.erase(operHandle); + if(!size) + return ErrorCode::INVALID_OPERATION_HANDLE; + else + return ErrorCode::OK; +} + +ErrorCode OperationContext::update(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb) { + ErrorCode errorCode = ErrorCode::OK; + if (input.size() > MAX_ALLOWED_INPUT_SIZE) { + int noOfChunks = input.size()/MAX_ALLOWED_INPUT_SIZE; + int extraData = input.size()%MAX_ALLOWED_INPUT_SIZE; + for(int i =0 ; i < noOfChunks; i++) { + auto first = input.cbegin() + (i*MAX_ALLOWED_INPUT_SIZE); + auto end = first + MAX_ALLOWED_INPUT_SIZE; + std::vector newInput(first, end); + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, newInput.data(), newInput.size(), + Operation::Update, cb))) { + return errorCode; + } + } + if(extraData > 0) { + std::vector finalInput(input.cend()-extraData, input.cend()); + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, finalInput.data(), finalInput.size(), + Operation::Update, cb))) { + return errorCode; + } + } + } else { + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, input.data(), input.size(), + Operation::Update, cb))) { + return errorCode; + } + } + return errorCode; +} + +ErrorCode OperationContext::finish(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb) { + ErrorCode errorCode = ErrorCode::OK; + if (input.size() > MAX_ALLOWED_INPUT_SIZE) { + int noOfChunks = input.size()/MAX_ALLOWED_INPUT_SIZE; + int extraData = input.size()%MAX_ALLOWED_INPUT_SIZE; + for(int i =0 ; i < noOfChunks; i++) { + auto first = input.cbegin() + (i*MAX_ALLOWED_INPUT_SIZE); + auto end = first + MAX_ALLOWED_INPUT_SIZE; + std::vector newInput(first, end); + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, newInput.data(), newInput.size(), + Operation::Finish, cb))) { + return errorCode; + } + } + if(extraData > 0) { + std::vector finalInput(input.cend()-extraData, input.cend()); + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, finalInput.data(), finalInput.size(), + Operation::Finish, cb))) { + return errorCode; + } + } + } else { + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, input.data(), input.size(), + Operation::Finish, cb))) { + return errorCode; + } + } + return errorCode; +} + +ErrorCode OperationContext::internalUpdate(uint64_t operHandle, uint8_t* input, size_t input_len, Operation opr, std::vector& out) { + int dataToSELen=0; + /*Length of the data consumed from input */ + int inputConsumed=0; + bool dataSendToSE = true; + int blockSize = 0; + BufferedData data = operationTable[operHandle].data; + int bufIndex = data.buf_len; + + if(Algorithm::AES == operationTable[operHandle].info.alg) { + blockSize = AES_BLOCK_SIZE; + } else if(Algorithm::TRIPLE_DES == operationTable[operHandle].info.alg) { + blockSize = DES_BLOCK_SIZE; + } + + if(data.buf_len > 0) { + if(opr == Operation::Finish) { + //Copy the buffer to be send to SE. + for(int i = 0; i < data.buf_len; i++) + { + out.push_back(data.buf[i]); + } + dataToSELen = data.buf_len + input_len; + } else { + if (data.buf_len + input_len >= blockSize) { + dataToSELen = data.buf_len + input_len; + //Copy the buffer to be send to SE. + for(int i = 0; i < data.buf_len; i++) + { + out.push_back(data.buf[i]); + } + } else { + dataSendToSE = false; + } + } + } else { + dataToSELen = input_len; + } + + if(dataSendToSE) { + if(opr == Operation::Update) { + dataToSELen = (dataToSELen/blockSize) * blockSize; + } + inputConsumed = dataToSELen - data.buf_len; + + //Copy the buffer to be send to SE. + for(int i = 0; i < inputConsumed; i++) + { + out.push_back(input[i]); + } + + /* All the data is consumed so clear buffer */ + if(data.buf_len != 0) { + memset(data.buf, 0x00, sizeof(data.buf)); + bufIndex = data.buf_len = 0; + } + } + + //Store the remaining buffer for later use. + data.buf_len += (input_len - inputConsumed); + for(int i = 0; i < (input_len - inputConsumed); i++) + { + data.buf[bufIndex+i] = input[inputConsumed+i]; + } + return ErrorCode::OK; +} + +} // namespace javacard +} // namespace V4_1 +} // namespace keymaster diff --git a/HAL/keymaster/Android.bp b/HAL/keymaster/Android.bp index 10bfe5d2..b3a21fa0 100644 --- a/HAL/keymaster/Android.bp +++ b/HAL/keymaster/Android.bp @@ -18,6 +18,7 @@ cc_library { srcs: [ "4.1/JavacardKeymaster4Device.cpp", "4.1/CborConverter.cpp", + "4.1/JavacardOperationContext.cpp", ], local_include_dirs: [ "include", diff --git a/HAL/keymaster/include/JavacardOperationContext.h b/HAL/keymaster/include/JavacardOperationContext.h new file mode 100644 index 00000000..e63b5011 --- /dev/null +++ b/HAL/keymaster/include/JavacardOperationContext.h @@ -0,0 +1,80 @@ +/* + ** + ** Copyright 2020, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#ifndef KEYMASTER_V4_1_JAVACARD_OPERATIONCONTEXT_H_ +#define KEYMASTER_V4_1_JAVACARD_OPERATIONCONTEXT_H_ + +#include +#include + +#define MAX_BUF_SIZE 32 + +namespace keymaster { +namespace V4_1 { +namespace javacard { + +using ::android::hardware::keymaster::V4_0::ErrorCode; +using ::android::hardware::keymaster::V4_0::Algorithm; +using ::android::hardware::keymaster::V4_0::KeyPurpose; + +using sendDataToSE_cb = std::function& data)>; + +enum class Operation; +struct OperationData; + +struct OperationInfo { + Algorithm alg; + KeyPurpose purpose; +}; + +class OperationContext { + +public: + OperationContext(){} + ~OperationContext() {} + ErrorCode setOperationData(uint64_t operationHandle, OperationInfo& oeprInfo); + ErrorCode getOperationData(uint64_t operHandle, OperationInfo& operInfo); + ErrorCode clearOperationData(uint64_t operationHandle); + ErrorCode update(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb); + ErrorCode finish(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb); + +private: + std::map operationTable; + ErrorCode internalUpdate(uint64_t operHandle, uint8_t* input, size_t input_len, Operation opr, std::vector& + out); + inline ErrorCode handleInternalUpdate(uint64_t operHandle, uint8_t* data, size_t len, Operation opr, + sendDataToSE_cb cb) { + ErrorCode errorCode = ErrorCode::OK; + std::vector out; + if(ErrorCode::OK != (errorCode = internalUpdate(operHandle, data, len, + opr, out))) { + return errorCode; + } + if(ErrorCode::OK != (errorCode = cb(out))) { + return errorCode; + } + return errorCode; + } + + +}; + +} // namespace javacard +} // namespace V4_1 +} // namespace keymaster + +#endif // KEYMASTER_V4_1_JAVACARD_OPERATIONCONTEXT_H_ From 3bedbe4dd83151891b435dc72bc751f96d4b6ea6 Mon Sep 17 00:00:00 2001 From: Prashant Patil Date: Mon, 15 Jun 2020 00:33:47 +0530 Subject: [PATCH 4/8] Added java_card_soft_keymaster_context extending pure soft keymaster context to support public key operations in JavaCardKeymaster HAL. It is used in public key operations such as RSA encryption, signature verification, exporting public key and also used for decoding pkcs8 key for importing. --- .../4.1/JavacardKeymaster4Device.cpp | 245 +++++++++---- .../4.1/java_card_soft_keymaster_context.cpp | 334 ++++++++++++++++++ HAL/keymaster/Android.bp | 1 + .../java_card_soft_keymaster_context.h | 68 ++++ 4 files changed, 570 insertions(+), 78 deletions(-) create mode 100644 HAL/keymaster/4.1/java_card_soft_keymaster_context.cpp create mode 100644 HAL/keymaster/include/java_card_soft_keymaster_context.h diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index 13342f94..11bcd8b9 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -27,6 +27,7 @@ #include #include +#include //#define JAVACARD_KEYMASTER_NAME "JavacardKeymaster4.1Device v0.1" //#define JAVACARD_KEYMASTER_AUTHOR "Android Open Source Project" @@ -149,9 +150,59 @@ class KmParamSet : public keymaster_key_param_set_t { ~KmParamSet() { delete[] params; } }; +static inline hidl_vec kmParamSet2Hidl(const keymaster_key_param_set_t& set) { + hidl_vec result; + if (set.length == 0 || set.params == nullptr) + return result; + + result.resize(set.length); + keymaster_key_param_t* params = set.params; + for (size_t i = 0; i < set.length; ++i) { + auto tag = params[i].tag; + result[i].tag = legacy_enum_conversion(tag); + switch (typeFromTag(tag)) { + case KM_ENUM: + case KM_ENUM_REP: + result[i].f.integer = params[i].enumerated; + break; + case KM_UINT: + case KM_UINT_REP: + result[i].f.integer = params[i].integer; + break; + case KM_ULONG: + case KM_ULONG_REP: + result[i].f.longInteger = params[i].long_integer; + break; + case KM_DATE: + result[i].f.dateTime = params[i].date_time; + break; + case KM_BOOL: + result[i].f.boolValue = params[i].boolean; + break; + case KM_BIGNUM: + case KM_BYTES: + result[i].blob.setToExternal(const_cast(params[i].blob.data), + params[i].blob.data_length); + break; + case KM_INVALID: + default: + params[i].tag = KM_TAG_INVALID; + /* just skip */ + break; + } + } + return result; +} + +inline hidl_vec kmBuffer2hidlVec(const ::keymaster::Buffer& buf) { + hidl_vec result; + result.setToExternal(const_cast(buf.peek_read()), buf.available_read()); + return result; +} + JavacardKeymaster4Device::JavacardKeymaster4Device(): softKm_(new ::keymaster::AndroidKeymaster( []() -> auto { - auto context = new PureSoftKeymasterContext(); + auto context = new JavaCardSoftKeymasterContext(); context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel()); return context; }(), @@ -423,6 +474,7 @@ Return JavacardKeymaster4Device::generateKey(const hidl_vec& Return JavacardKeymaster4Device::importKey(const hidl_vec& keyParams, KeyFormat keyFormat, const hidl_vec& keyData, importKey_cb _hidl_cb) { keymaster_error_t error = KM_ERROR_UNKNOWN_ERROR; hidl_vec inKey; + KeymasterKeyBlob key_material; if (keyFormat == KeyFormat::PKCS8) { ImportKeyRequest request; @@ -437,13 +489,8 @@ Return JavacardKeymaster4Device::importKey(const hidl_vec& k hidl_vec resultKeyBlob; error = response.error; if (response.error == KM_ERROR_OK) { - AuthorizationSet hidden; - error = BuildHiddenAuthorizations(request.key_description, &hidden, softwareRootOfTrust); - if (error == KM_ERROR_OK) { - DeserializeIntegrityAssuredBlob(KeymasterKeyBlob(response.key_blob), hidden, &key_material, &response.enforced, &response.unenforced); - - inKey.setToExternal(const_cast(key_material.key_material), key_material.key_material_size); - } + key_material = KeymasterKeyBlob(response.key_blob); + inKey.setToExternal(const_cast(key_material.key_material), key_material.key_material_size); } if(error != KM_ERROR_OK) { KeyCharacteristics resultCharacteristics; @@ -546,14 +593,30 @@ Return JavacardKeymaster4Device::getKeyCharacteristics(const hidl_vec JavacardKeymaster4Device::exportKey(KeyFormat keyFormat, const hidl_vec& keyBlob, const hidl_vec& clientId, const hidl_vec& appData, exportKey_cb _hidl_cb) { +Return JavacardKeymaster4Device::exportKey(KeyFormat exportFormat, const hidl_vec& keyBlob, const hidl_vec& /*clientId*/, const hidl_vec& /*appData*/, exportKey_cb _hidl_cb) { + + ExportKeyRequest request; + request.key_format = legacy_enum_conversion(exportFormat); + request.SetKeyMaterial(keyBlob.data(), keyBlob.size()); + //addClientAndAppData(clientId, appData, &request.additional_params); + + ExportKeyResponse response; + softKm_->ExportKey(request, &response); + + hidl_vec resultKeyBlob; + if (response.error == KM_ERROR_OK) { + resultKeyBlob.setToExternal(response.key_data, response.key_data_length); + } + _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob); + return Void(); +/* cppbor::Array array; std::unique_ptr item; hidl_vec keyMaterial; std::vector cborOutData; ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; - array.add(static_cast(keyFormat)); + array.add(static_cast(exportFormat)); array.add(std::vector(keyBlob)); array.add(std::vector(clientId)); array.add(std::vector(appData)); @@ -570,7 +633,7 @@ Return JavacardKeymaster4Device::exportKey(KeyFormat keyFormat, const hidl } } _hidl_cb(errorCode, keyMaterial); - return Void(); + return Void();*/ } Return JavacardKeymaster4Device::attestKey(const hidl_vec& keyToAttest, const hidl_vec& attestParams, attestKey_cb _hidl_cb) { @@ -680,49 +743,45 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< hidl_vec outParams; uint64_t operationHandle = 0; - if (/*KeyPurpose::ENCRYPT == purpose ||*/ KeyPurpose::VERIFY == purpose) { - + if (KeyPurpose::ENCRYPT == purpose || KeyPurpose::VERIFY == purpose) { BeginOperationRequest request; request.purpose = legacy_enum_conversion(purpose); request.SetKeyMaterial(keyBlob.data(), keyBlob.size()); request.additional_params.Reinitialize(KmParamSet(inParams)); - //TODO need to check AUTH_TOKEN will work here? - //hidl_vec hidl_vec_token = authToken2HidlVec(authToken); - //request.additional_params.push_back( - // TAG_AUTH_TOKEN, reinterpret_cast(hidl_vec_token.data()), hidl_vec_token.size()); - BeginOperationResponse response; softKm_->BeginOperation(request, &response); - //hidl_vec resultParams; - //if (response.error == KM_ERROR_OK) resultParams = kmParamSet2Hidl(response.output_params); + hidl_vec resultParams; + if (response.error == KM_ERROR_OK) { + resultParams = kmParamSet2Hidl(response.output_params); + } + if (response.error != KM_ERROR_INCOMPATIBLE_ALGORITHM) { /*Incompatible algorithm could be handled by JavaCard*/ + _hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle); + return Void(); + } + } - //_hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle); - return Void(); - /* Public key operations are handled here*/ - } else { - cppbor::Array array; - std::vector cborOutData; - std::unique_ptr item; + cppbor::Array array; + std::vector cborOutData; + std::unique_ptr item; - /* Convert input data to cbor format */ - array.add(static_cast(purpose)); - array.add(std::vector(keyBlob)); - cborConverter_.addKeyparameters(array, inParams); - cborConverter_.addHardwareAuthToken(array, authToken); - std::vector cborData = array.encode(); + /* Convert input data to cbor format */ + array.add(static_cast(purpose)); + array.add(std::vector(keyBlob)); + cborConverter_.addKeyparameters(array, inParams); + cborConverter_.addHardwareAuthToken(array, authToken); + std::vector cborData = array.encode(); errorCode = sendData(this, pTransportFactory, Instruction::INS_BEGIN_OPERATION_CMD, cborData, cborOutData); - if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { - //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), - true); - if (item != nullptr) { - cborConverter_.getKeyParameters(item, 1, outParams); - cborConverter_.getUint64(item, 2, operationHandle); - } + if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { + //Skip last 2 bytes in cborData, it contains status. + std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), + true); + if (item != nullptr) { + cborConverter_.getKeyParameters(item, 1, outParams); + cborConverter_.getUint64(item, 2, operationHandle); } } _hidl_cb(errorCode, outParams, operationHandle); @@ -730,32 +789,47 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< } Return JavacardKeymaster4Device::update(uint64_t operationHandle, const hidl_vec& inParams, const hidl_vec& input, const HardwareAuthToken& authToken, const VerificationToken& verificationToken, update_cb _hidl_cb) { - cppbor::Array array; - std::unique_ptr item; - std::vector cborOutData; ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; - hidl_vec outParams; + UpdateOperationRequest request; + request.op_handle = operationHandle; + request.input.Reinitialize(input.data(), input.size()); + request.additional_params.Reinitialize(KmParamSet(inParams)); + + UpdateOperationResponse response; + softKm_->UpdateOperation(request, &response); + uint32_t inputConsumed = 0; + hidl_vec outParams; hidl_vec output; + errorCode = legacy_enum_conversion(response.error); + if (response.error == KM_ERROR_OK) { + inputConsumed = response.input_consumed; + outParams = kmParamSet2Hidl(response.output_params); + output = kmBuffer2hidlVec(response.output); + } else if(response.error == KM_ERROR_INVALID_OPERATION_HANDLE) { + cppbor::Array array; + std::unique_ptr item; + std::vector cborOutData; - /* Convert input data to cbor format */ - array.add(operationHandle); - cborConverter_.addKeyparameters(array, inParams); - array.add(std::vector(input)); - cborConverter_.addHardwareAuthToken(array, authToken); - cborConverter_.addVerificationToken(array, verificationToken); - std::vector cborData = array.encode(); + // Convert input data to cbor format + array.add(operationHandle); + cborConverter_.addKeyparameters(array, inParams); + array.add(std::vector(input)); + cborConverter_.addHardwareAuthToken(array, authToken); + cborConverter_.addVerificationToken(array, verificationToken); + std::vector cborData = array.encode(); errorCode = sendData(this, pTransportFactory, Instruction::INS_UPDATE_OPERATION_CMD, cborData, cborOutData); - if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { - //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), - true); - if (item != nullptr) { - cborConverter_.getUint64(item, 1, inputConsumed); - cborConverter_.getKeyParameters(item, 2, outParams); - cborConverter_.getBinaryArray(item, 3, output); + if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { + //Skip last 2 bytes in cborData, it contains status. + std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), + true); + if (item != nullptr) { + cborConverter_.getUint64(item, 1, inputConsumed); + cborConverter_.getKeyParameters(item, 2, outParams); + cborConverter_.getBinaryArray(item, 3, output); + } } } _hidl_cb(errorCode, inputConsumed, outParams, output); @@ -763,31 +837,46 @@ Return JavacardKeymaster4Device::update(uint64_t operationHandle, const hi } Return JavacardKeymaster4Device::finish(uint64_t operationHandle, const hidl_vec& inParams, const hidl_vec& input, const hidl_vec& signature, const HardwareAuthToken& authToken, const VerificationToken& verificationToken, finish_cb _hidl_cb) { - cppbor::Array array; - std::unique_ptr item; - std::vector cborOutData; ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; + FinishOperationRequest request; + request.op_handle = operationHandle; + request.input.Reinitialize(input.data(), input.size()); + request.signature.Reinitialize(signature.data(), signature.size()); + request.additional_params.Reinitialize(KmParamSet(inParams)); + + FinishOperationResponse response; + softKm_->FinishOperation(request, &response); + hidl_vec outParams; hidl_vec output; + errorCode = legacy_enum_conversion(response.error); + if (response.error == KM_ERROR_OK) { + outParams = kmParamSet2Hidl(response.output_params); + output = kmBuffer2hidlVec(response.output); + } else if (response.error == KM_ERROR_INVALID_OPERATION_HANDLE) { + cppbor::Array array; + std::unique_ptr item; + std::vector cborOutData; - /* Convert input data to cbor format */ - array.add(operationHandle); - cborConverter_.addKeyparameters(array, inParams); - array.add(std::vector(input)); - array.add(std::vector(signature)); - cborConverter_.addHardwareAuthToken(array, authToken); - cborConverter_.addVerificationToken(array, verificationToken); - std::vector cborData = array.encode(); + // Convert input data to cbor format + array.add(operationHandle); + cborConverter_.addKeyparameters(array, inParams); + array.add(std::vector(input)); + array.add(std::vector(signature)); + cborConverter_.addHardwareAuthToken(array, authToken); + cborConverter_.addVerificationToken(array, verificationToken); + std::vector cborData = array.encode(); errorCode = sendData(this, pTransportFactory, Instruction::INS_FINISH_OPERATION_CMD, cborData, cborOutData); - if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { - //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), - true); - if (item != nullptr) { - cborConverter_.getKeyParameters(item, 1, outParams); - cborConverter_.getBinaryArray(item, 2, output); + if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { + //Skip last 2 bytes in cborData, it contains status. + std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), + true); + if (item != nullptr) { + cborConverter_.getKeyParameters(item, 1, outParams); + cborConverter_.getBinaryArray(item, 2, output); + } } } _hidl_cb(errorCode, outParams, output); diff --git a/HAL/keymaster/4.1/java_card_soft_keymaster_context.cpp b/HAL/keymaster/4.1/java_card_soft_keymaster_context.cpp new file mode 100644 index 00000000..76731d5d --- /dev/null +++ b/HAL/keymaster/4.1/java_card_soft_keymaster_context.cpp @@ -0,0 +1,334 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +using std::unique_ptr; + +namespace keymaster { + +JavaCardSoftKeymasterContext::JavaCardSoftKeymasterContext(keymaster_security_level_t security_level) + : PureSoftKeymasterContext(security_level) {} + +JavaCardSoftKeymasterContext::~JavaCardSoftKeymasterContext() {} + +keymaster_error_t JavaCardSoftKeymasterContext::CreateKeyBlob(const AuthorizationSet& key_description, + const keymaster_key_origin_t origin, + const KeymasterKeyBlob& key_material, + KeymasterKeyBlob* blob, + AuthorizationSet* hw_enforced, + AuthorizationSet* sw_enforced) const { + if (key_description.GetTagValue(TAG_ROLLBACK_RESISTANCE)) { + return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE; + } + + keymaster_error_t error = SetKeyBlobAuthorizations(key_description, origin, os_version_, + os_patchlevel_, hw_enforced, sw_enforced); + if (error != KM_ERROR_OK) return error; + + AuthorizationSet hidden; + error = BuildHiddenAuthorizations(key_description, &hidden, softwareRootOfTrust); + if (error != KM_ERROR_OK) return error; + + size_t size = key_material.SerializedSize(); + + if (!blob->Reset(size)) + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + + uint8_t* p = blob->writable_data(); + p = key_material.Serialize(p, blob->end()); + + return KM_ERROR_OK; +} + +inline keymaster_tag_t legacy_enum_conversion(const Tag value) { + return keymaster_tag_t(value); +} + +inline Tag legacy_enum_conversion(const keymaster_tag_t value) { + return Tag(value); +} + +inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) { + return keymaster_tag_get_type(tag); +} + +keymaster_key_param_set_t hidlKeyParams2Km(const hidl_vec& keyParams) { + keymaster_key_param_set_t set; + + set.params = new keymaster_key_param_t[keyParams.size()]; + set.length = keyParams.size(); + + for (size_t i = 0; i < keyParams.size(); ++i) { + auto tag = legacy_enum_conversion(keyParams[i].tag); + switch (typeFromTag(tag)) { + case KM_ENUM: + case KM_ENUM_REP: + set.params[i] = keymaster_param_enum(tag, keyParams[i].f.integer); + break; + case KM_UINT: + case KM_UINT_REP: + set.params[i] = keymaster_param_int(tag, keyParams[i].f.integer); + break; + case KM_ULONG: + case KM_ULONG_REP: + set.params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger); + break; + case KM_DATE: + set.params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime); + break; + case KM_BOOL: + if (keyParams[i].f.boolValue) + set.params[i] = keymaster_param_bool(tag); + else + set.params[i].tag = KM_TAG_INVALID; + break; + case KM_BIGNUM: + case KM_BYTES: + set.params[i] = + keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size()); + break; + case KM_INVALID: + default: + set.params[i].tag = KM_TAG_INVALID; + /* just skip */ + break; + } + } + + return set; +} + +class KmParamSet : public keymaster_key_param_set_t { + public: + explicit KmParamSet(const hidl_vec& keyParams) + : keymaster_key_param_set_t(hidlKeyParams2Km(keyParams)) {} + KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} { + other.length = 0; + other.params = nullptr; + } + KmParamSet(const KmParamSet&) = delete; + ~KmParamSet() { delete[] params; } +}; + +EVP_PKEY* RSA_fromMaterial(const uint8_t* modulus, size_t mod_size) { + BIGNUM *n = BN_bin2bn(modulus, mod_size, NULL); + BIGNUM *e = BN_new();//bignum_decode(exp, 5); + char exp[] = "65537"; + BN_dec2bn(&e, exp); + + if (!n || !e) + return NULL; + + if (e && n) { + EVP_PKEY* pRsaKey = EVP_PKEY_new(); + RSA* rsa = RSA_new(); + rsa->e = e; + rsa->n = n; + EVP_PKEY_assign_RSA(pRsaKey, rsa); + return pRsaKey; + } else { + if (n) BN_free(n); + if (e) BN_free(e); + return NULL; + } +} + +EC_GROUP* ChooseGroup(keymaster_ec_curve_t ec_curve) { + switch (ec_curve) { + case KM_EC_CURVE_P_224: + return EC_GROUP_new_by_curve_name(NID_secp224r1); + break; + case KM_EC_CURVE_P_256: + return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + break; + case KM_EC_CURVE_P_384: + return EC_GROUP_new_by_curve_name(NID_secp384r1); + break; + case KM_EC_CURVE_P_521: + return EC_GROUP_new_by_curve_name(NID_secp521r1); + break; + default: + return nullptr; + break; + } +} + +EVP_PKEY* EC_fromMaterial(const uint8_t* pub_key, size_t key_size, keymaster_ec_curve_t ec_curve) { + + EC_GROUP *ec_group = ChooseGroup(ec_curve); + EC_POINT *p = EC_POINT_new(ec_group); + EC_KEY *ec_key = EC_KEY_new(); + EVP_PKEY *pEcKey = EVP_PKEY_new(); + + if((EC_KEY_set_group(ec_key, ec_group) != 1) || (EC_POINT_oct2point(ec_group, p, pub_key, key_size, NULL) != 1) + || (EC_KEY_set_public_key(ec_key, p) != 1) || (EVP_PKEY_set1_EC_KEY(pEcKey, ec_key) != 1)) { + return NULL; + } + + return pEcKey; +} + +keymaster_error_t JavaCardSoftKeymasterContext::LoadKey(const keymaster_algorithm_t algorithm, KeymasterKeyBlob&& key_material, + AuthorizationSet&& hw_enforced, + AuthorizationSet&& sw_enforced, + UniquePtr* key) const { + auto factory = (AsymmetricKeyFactory*)GetKeyFactory(algorithm); + UniquePtr asym_key; + keymaster_error_t error = KM_ERROR_OK; + const uint8_t* tmp = key_material.key_material; + const size_t temp_size = key_material.key_material_size; + EVP_PKEY* pkey = NULL; + + if(algorithm == KM_ALGORITHM_RSA) { + pkey = RSA_fromMaterial(tmp, temp_size); + } else if(algorithm == KM_ALGORITHM_EC) { + keymaster_ec_curve_t ec_curve = KM_EC_CURVE_P_256; + if (!hw_enforced.GetTagValue(TAG_EC_CURVE, &ec_curve) && + !sw_enforced.GetTagValue(TAG_EC_CURVE, &ec_curve)) { + return KM_ERROR_INVALID_ARGUMENT; + }//TODO also get ec_curve based on key size + pkey = EC_fromMaterial(tmp, temp_size, ec_curve); + } + if (!pkey) + return TranslateLastOpenSslError(); + UniquePtr pkey_deleter(pkey); + + error = factory->CreateEmptyKey(move(hw_enforced), move(sw_enforced), &asym_key); + if (error != KM_ERROR_OK) + return error; + + asym_key->key_material() = move(key_material); + if (!asym_key->EvpToInternal(pkey)) + error = TranslateLastOpenSslError(); + else + key->reset(asym_key.release()); + + return error; +} + +keymaster_error_t JavaCardSoftKeymasterContext::ParseKeyBlob(const KeymasterKeyBlob& blob, + const AuthorizationSet& /*additional_params*/, + UniquePtr* key) const { + + // The JavaCardSoftKeymasterContext handle a key blob generated by JavaCard keymaster for public key operations. + // + // 1. A JavaCard keymaster key blob is a CborEncoded data of Secret, Nonce, AuthTag, KeyCharectristics and Public key. + // Here in public key operation we need only KeyCharectristics and Public key. + // Once these values extracted Public key is created based on parameters and returned. + // + + AuthorizationSet hw_enforced; + AuthorizationSet sw_enforced; + KeymasterKeyBlob key_material; + keymaster_error_t error; + + auto constructKey = [&, this] () mutable -> keymaster_error_t { + keymaster_algorithm_t algorithm; + if (!hw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm) && + !sw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm)) { + return KM_ERROR_INVALID_ARGUMENT; + } + + if (algorithm != KM_ALGORITHM_RSA && algorithm != KM_ALGORITHM_EC) { + return KM_ERROR_INCOMPATIBLE_ALGORITHM; + } + error = LoadKey(algorithm, move(key_material), move(hw_enforced), + move(sw_enforced), key); + return error; + }; + + CborConverter cc; + std::unique_ptr item; + ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; + std::vector cborKey(blob.key_material_size); +// std::vector cborKey(187); + + for(size_t i = 0; i < blob.key_material_size; i++) { + cborKey[i] = blob.key_material[i]; + } +/*uint8_t tempBlob[] = {0x85, 0x58, 0x20, 0xDA, 0x29, 0xC7, 0x1A, 0x8C, 0xE7, 0x6A, 0x0D, 0xFD, +0x2E, 0x53, 0x06, 0x81, 0x85, 0x37, 0x2D, 0x9E, 0x74, 0xE7, 0xF1, 0xD5, +0x3F, 0x0E, 0xAB, 0x1A, 0xF8, 0xE9, 0x46, 0xFD, 0xDC, 0x37, 0x54, 0x4C, +0xE9, 0xA7, 0xD0, 0x71, 0x96, 0xCC, 0x66, 0x18, 0xF0, 0x53, 0xD1, 0x30, +0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x82, 0xA1, 0x1A, 0x30, 0x00, 0x01, 0xF5, 0x1A, 0x01, 0x02, 0x03, +0x04, 0xA6, 0x1A, 0x10, 0x00, 0x00, 0x02, 0x03, 0x1A, 0x50, 0x00, 0x00, +0xC8, 0x1A, 0x00, 0x01, 0x00, 0x01, 0x1A, 0x30, 0x00, 0x00, 0x03, 0x19, +0x01, 0x00, 0x1A, 0x10, 0x00, 0x02, 0xBE, 0x00, 0x1A, 0x30, 0x00, 0x02, +0xC1, 0x00, 0x1A, 0x30, 0x00, 0x02, 0xC2, 0x1A, 0x00, 0x03, 0x15, 0x14, +0x58, 0x41, 0x04, 0x2B, 0xF1, 0x84, 0xD4, 0xFB, 0x63, 0x44, 0x20, 0xD0, +0xA3, 0x7D, 0x6A, 0xC1, 0xC5, 0x26, 0x12, 0xCD, 0x79, 0x77, 0x81, 0x22, +0x33, 0x30, 0x70, 0xF7, 0x25, 0x6D, 0x75, 0xE0, 0xD4, 0xD0, 0x50, 0xD6, +0x80, 0x65, 0x2A, 0x44, 0x0B, 0x8E, 0xFC, 0xA0, 0x8B, 0xC5, 0xF4, 0x8A, +0xCA, 0x4B, 0x89, 0x6E, 0x8B, 0xFC, 0x38, 0xB7, 0xC9, 0xB9, 0xB6, 0xE7, +0x57, 0xE6, 0x53, 0xE9, 0xBF, 0x94, 0x3A}; + for(size_t i = 0; i < 187; i++) { + cborKey[i] = tempBlob[i]; + } +*/ + std::tie(item, errorCode) = cc.decodeData(cborKey, false); + if (item != nullptr) { + std::vector temp; + cc.getBinaryArray(item, 4, temp); + + key_material = {temp.data(), temp.size()}; + temp.clear(); + KeyCharacteristics keyCharacteristics; + cc.getKeyCharacteristics(item, 3, keyCharacteristics); + + sw_enforced.Reinitialize(KmParamSet(keyCharacteristics.softwareEnforced)); + hw_enforced.Reinitialize(KmParamSet(keyCharacteristics.hardwareEnforced)); + } + return constructKey(); +} +} // namespace keymaster diff --git a/HAL/keymaster/Android.bp b/HAL/keymaster/Android.bp index b3a21fa0..33136850 100644 --- a/HAL/keymaster/Android.bp +++ b/HAL/keymaster/Android.bp @@ -18,6 +18,7 @@ cc_library { srcs: [ "4.1/JavacardKeymaster4Device.cpp", "4.1/CborConverter.cpp", + "4.1/java_card_soft_keymaster_context.cpp", "4.1/JavacardOperationContext.cpp", ], local_include_dirs: [ diff --git a/HAL/keymaster/include/java_card_soft_keymaster_context.h b/HAL/keymaster/include/java_card_soft_keymaster_context.h new file mode 100644 index 00000000..07be5c9e --- /dev/null +++ b/HAL/keymaster/include/java_card_soft_keymaster_context.h @@ -0,0 +1,68 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYSTEM_KEYMASTER_JAVA_CARD_SOFT_KEYMASTER_CONTEXT_H_ +#define SYSTEM_KEYMASTER_JAVA_CARD_SOFT_KEYMASTER_CONTEXT_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace keymaster { + +class SoftKeymasterKeyRegistrations; +class Keymaster0Engine; +class Keymaster1Engine; +class Key; + +/** + * SoftKeymasterContext provides the context for a non-secure implementation of AndroidKeymaster. + */ +class JavaCardSoftKeymasterContext : public keymaster::PureSoftKeymasterContext { + keymaster_error_t LoadKey(const keymaster_algorithm_t algorithm, KeymasterKeyBlob&& key_material, + AuthorizationSet&& hw_enforced, + AuthorizationSet&& sw_enforced, + UniquePtr* key) const; + public: + // Security level must only be used for testing. + explicit JavaCardSoftKeymasterContext( + keymaster_security_level_t security_level = KM_SECURITY_LEVEL_SOFTWARE); + ~JavaCardSoftKeymasterContext() override; + + keymaster_error_t ParseKeyBlob(const KeymasterKeyBlob& blob, + const AuthorizationSet& additional_params, + UniquePtr* key) const override; + /********************************************************************************************* + * Implement SoftwareKeyBlobMaker + */ + keymaster_error_t CreateKeyBlob(const AuthorizationSet& auths, keymaster_key_origin_t origin, + const KeymasterKeyBlob& key_material, KeymasterKeyBlob* blob, + AuthorizationSet* hw_enforced, + AuthorizationSet* sw_enforced) const override; + +}; + +} // namespace keymaster + +#endif // SYSTEM_KEYMASTER_PURE_SOFT_KEYMASTER_CONTEXT_H_ From 76d43caf42ca3526e801dafd0280855633a3bd39 Mon Sep 17 00:00:00 2001 From: BKSSM Venkateswarlu Date: Mon, 15 Jun 2020 04:51:05 +0530 Subject: [PATCH 5/8] Added validations in OperationContext --- .../4.1/JavacardOperationContext.cpp | 86 +++++++++++++++---- .../include/JavacardOperationContext.h | 50 +++++++++-- 2 files changed, 113 insertions(+), 23 deletions(-) diff --git a/HAL/keymaster/4.1/JavacardOperationContext.cpp b/HAL/keymaster/4.1/JavacardOperationContext.cpp index 096ace36..185960d0 100644 --- a/HAL/keymaster/4.1/JavacardOperationContext.cpp +++ b/HAL/keymaster/4.1/JavacardOperationContext.cpp @@ -18,8 +18,10 @@ #include #define MAX_ALLOWED_INPUT_SIZE 512 -#define AES_BLOCK_SIZE 16 -#define DES_BLOCK_SIZE 8 +#define AES_BLOCK_SIZE 16 +#define DES_BLOCK_SIZE 8 +#define RSA_INPUT_MSG_LEN 245 /*(256-11)*/ +#define EC_INPUT_MSG_LEN 32 namespace keymaster { namespace V4_1 { @@ -30,25 +32,15 @@ enum class Operation { Finish = 1 }; -struct BufferedData { - uint8_t buf[MAX_BUF_SIZE]; - int buf_len; -}; - -struct OperationData { - OperationInfo info; - BufferedData data; -}; - -ErrorCode OperationContext::setOperationData(uint64_t operationHandle, OperationInfo& operInfo) { +ErrorCode OperationContext::setOperationInfo(uint64_t operationHandle, OperationInfo& operInfo) { OperationData data; data.info = operInfo; operationTable[operationHandle] = data; return ErrorCode::OK; } -ErrorCode OperationContext::getOperationData(uint64_t operHandle, OperationInfo& operInfo) { +ErrorCode OperationContext::getOperationInfo(uint64_t operHandle, OperationInfo& operInfo) { auto itr = operationTable.find(operHandle); if(itr != operationTable.end()) { operInfo = itr->second.info; @@ -65,8 +57,50 @@ ErrorCode OperationContext::clearOperationData(uint64_t operHandle) { return ErrorCode::OK; } -ErrorCode OperationContext::update(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb) { +ErrorCode OperationContext::validateInputData(uint64_t operHandle, Operation opr, std::vector& actualInput, std::vector& input) { + ErrorCode errorCode = ErrorCode::OK; + OperationData oprData; + + if(ErrorCode::OK != (errorCode = getOperationData(operHandle, oprData))) { + return errorCode; + } + + if(Algorithm::RSA == oprData.info.alg && Digest::NONE == oprData.info.digest) { + if(actualInput.size() > RSA_INPUT_MSG_LEN) + return ErrorCode::INVALID_INPUT_LENGTH; + } else if(Algorithm::EC == oprData.info.alg && Digest::NONE == oprData.info.digest) { + if(actualInput.size() > EC_INPUT_MSG_LEN) { + /* Silently truncate the input */ + for(int i=0; i < EC_INPUT_MSG_LEN; i++) { + input.push_back(actualInput[i]); + } + return errorCode; + } + } + + if(opr == Operation::Finish) { + if(oprData.info.pad == PaddingMode::NONE && oprData.info.alg == Algorithm::AES) { + if(((oprData.data.buf_len+actualInput.size()) % AES_BLOCK_SIZE) != 0) + return ErrorCode::INVALID_INPUT_LENGTH; + } + if(oprData.info.pad == PaddingMode::NONE && oprData.info.alg == Algorithm::TRIPLE_DES) { + if(((oprData.data.buf_len+actualInput.size()) % DES_BLOCK_SIZE) != 0) + return ErrorCode::INVALID_INPUT_LENGTH; + } + } + input = actualInput; + return errorCode; +} + +ErrorCode OperationContext::update(uint64_t operHandle, std::vector& actualInput, sendDataToSE_cb cb) { ErrorCode errorCode = ErrorCode::OK; + std::vector input; + + /* Validate the input data */ + if(ErrorCode::OK != (errorCode = validateInputData(operHandle, Operation::Update, actualInput, input))) { + return errorCode; + } + if (input.size() > MAX_ALLOWED_INPUT_SIZE) { int noOfChunks = input.size()/MAX_ALLOWED_INPUT_SIZE; int extraData = input.size()%MAX_ALLOWED_INPUT_SIZE; @@ -95,8 +129,16 @@ ErrorCode OperationContext::update(uint64_t operHandle, std::vector& in return errorCode; } -ErrorCode OperationContext::finish(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb) { +ErrorCode OperationContext::finish(uint64_t operHandle, std::vector& actualInput, sendDataToSE_cb cb) { ErrorCode errorCode = ErrorCode::OK; + std::vector input; + OperationData oprData; + + /* Validate the input data */ + if(ErrorCode::OK != (errorCode = validateInputData(operHandle, Operation::Update, actualInput, input))) { + return errorCode; + } + if (input.size() > MAX_ALLOWED_INPUT_SIZE) { int noOfChunks = input.size()/MAX_ALLOWED_INPUT_SIZE; int extraData = input.size()%MAX_ALLOWED_INPUT_SIZE; @@ -122,6 +164,18 @@ ErrorCode OperationContext::finish(uint64_t operHandle, std::vector& in return errorCode; } } + + if(ErrorCode::OK != (errorCode = getOperationData(operHandle, oprData))) { + return errorCode; + } + + /* Send if any buffered data is remaining */ + if(oprData.data.buf_len > 0) { + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, nullptr, 0, + Operation::Finish, cb))) { + return errorCode; + } + } return errorCode; } diff --git a/HAL/keymaster/include/JavacardOperationContext.h b/HAL/keymaster/include/JavacardOperationContext.h index e63b5011..a1763650 100644 --- a/HAL/keymaster/include/JavacardOperationContext.h +++ b/HAL/keymaster/include/JavacardOperationContext.h @@ -30,15 +30,28 @@ namespace javacard { using ::android::hardware::keymaster::V4_0::ErrorCode; using ::android::hardware::keymaster::V4_0::Algorithm; using ::android::hardware::keymaster::V4_0::KeyPurpose; +using ::android::hardware::keymaster::V4_0::Digest; +using ::android::hardware::keymaster::V4_0::PaddingMode; using sendDataToSE_cb = std::function& data)>; enum class Operation; -struct OperationData; + +struct BufferedData { + uint8_t buf[MAX_BUF_SIZE]; + int buf_len; +}; struct OperationInfo { Algorithm alg; KeyPurpose purpose; + Digest digest; + PaddingMode pad; +}; + +struct OperationData { + OperationInfo info; + BufferedData data; }; class OperationContext { @@ -46,31 +59,54 @@ class OperationContext { public: OperationContext(){} ~OperationContext() {} - ErrorCode setOperationData(uint64_t operationHandle, OperationInfo& oeprInfo); - ErrorCode getOperationData(uint64_t operHandle, OperationInfo& operInfo); + ErrorCode setOperationInfo(uint64_t operationHandle, OperationInfo& oeprInfo); + ErrorCode getOperationInfo(uint64_t operHandle, OperationInfo& operInfo); ErrorCode clearOperationData(uint64_t operationHandle); ErrorCode update(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb); ErrorCode finish(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb); private: std::map operationTable; + + inline ErrorCode getOperationData(uint64_t operHandle, OperationData& oprData) { + auto itr = operationTable.find(operHandle); + if(itr != operationTable.end()) { + oprData = itr->second; + return ErrorCode::OK; + } + return ErrorCode::INVALID_OPERATION_HANDLE; + } + + ErrorCode validateInputData(uint64_t operHandle, Operation opr, std::vector& actualInput, + std::vector& input); ErrorCode internalUpdate(uint64_t operHandle, uint8_t* input, size_t input_len, Operation opr, std::vector& out); inline ErrorCode handleInternalUpdate(uint64_t operHandle, uint8_t* data, size_t len, Operation opr, sendDataToSE_cb cb) { ErrorCode errorCode = ErrorCode::OK; std::vector out; - if(ErrorCode::OK != (errorCode = internalUpdate(operHandle, data, len, - opr, out))) { + OperationData oprData; + + if(ErrorCode::OK != (errorCode = getOperationData(operHandle, oprData))) { return errorCode; } + + if(Algorithm::AES == oprData.info.alg || Algorithm::TRIPLE_DES == oprData.info.alg) { + if(ErrorCode::OK != (errorCode = internalUpdate(operHandle, data, len, + opr, out))) { + return errorCode; + } + } else { + /* Other algorithms no buffering required */ + for(int i = 0; i < len; i++) { + out.push_back(data[i]); + } + } if(ErrorCode::OK != (errorCode = cb(out))) { return errorCode; } return errorCode; } - - }; } // namespace javacard From 5402afb5f4f246addd4dd98f04541d077a29b487 Mon Sep 17 00:00:00 2001 From: BKSSM Venkateswarlu Date: Mon, 15 Jun 2020 22:22:41 +0530 Subject: [PATCH 6/8] Integration of OperationContext with JavacardKeymaster4Device class --- .../4.1/JavacardKeymaster4Device.cpp | 138 ++++++++++++------ .../4.1/JavacardOperationContext.cpp | 45 ++++-- .../include/JavacardKeymaster4Device.h | 2 + .../include/JavacardOperationContext.h | 18 ++- 4 files changed, 141 insertions(+), 62 deletions(-) diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index 11bcd8b9..c9ebb70f 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -206,7 +206,7 @@ JavacardKeymaster4Device::JavacardKeymaster4Device(): softKm_(new ::keymaster::A context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel()); return context; }(), - kOperationTableSize)), setUpBootParams(false) { + kOperationTableSize)), oprCtx_(new OperationContext()), setUpBootParams(false) { pTransportFactory = std::unique_ptr(new se_transport::TransportFactory( android::base::GetBoolProperty("ro.kernel.qemu", false))); pTransportFactory->openConnection(); @@ -773,7 +773,7 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< cborConverter_.addHardwareAuthToken(array, authToken); std::vector cborData = array.encode(); - errorCode = sendData(this, pTransportFactory, Instruction::INS_BEGIN_OPERATION_CMD, cborData, cborOutData); + errorCode = sendData(this, pTransportFactory, Instruction::INS_BEGIN_OPERATION_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. @@ -782,6 +782,8 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< if (item != nullptr) { cborConverter_.getKeyParameters(item, 1, outParams); cborConverter_.getUint64(item, 2, operationHandle); + /* Store the operationInfo */ + oprCtx_->setOperationInfo(operationHandle, purpose, inParams); } } _hidl_cb(errorCode, outParams, operationHandle); @@ -807,29 +809,44 @@ Return JavacardKeymaster4Device::update(uint64_t operationHandle, const hi outParams = kmParamSet2Hidl(response.output_params); output = kmBuffer2hidlVec(response.output); } else if(response.error == KM_ERROR_INVALID_OPERATION_HANDLE) { - cppbor::Array array; - std::unique_ptr item; - std::vector cborOutData; - - // Convert input data to cbor format - array.add(operationHandle); - cborConverter_.addKeyparameters(array, inParams); - array.add(std::vector(input)); - cborConverter_.addHardwareAuthToken(array, authToken); - cborConverter_.addVerificationToken(array, verificationToken); - std::vector cborData = array.encode(); - - errorCode = sendData(this, pTransportFactory, Instruction::INS_UPDATE_OPERATION_CMD, cborData, cborOutData); - - if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { - //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), - true); - if (item != nullptr) { - cborConverter_.getUint64(item, 1, inputConsumed); - cborConverter_.getKeyParameters(item, 2, outParams); - cborConverter_.getBinaryArray(item, 3, output); + std::vector tempOut; + /* OperationContext calls this below sendDataCallback callback function. This callback + * may be called multiple times if the input data is larger than MAX_ALLOWED_INPUT_SIZE. + */ + auto sendDataCallback = [&](std::vector& data, bool) -> ErrorCode { + cppbor::Array array; + std::unique_ptr item; + std::vector cborOutData; + + // Convert input data to cbor format + array.add(operationHandle); + cborConverter_.addKeyparameters(array, inParams); + array.add(data); + cborConverter_.addHardwareAuthToken(array, authToken); + cborConverter_.addVerificationToken(array, verificationToken); + std::vector cborData = array.encode(); + + errorCode = sendData(this, pTransportFactory, Instruction::INS_UPDATE_OPERATION_CMD, cborData, cborOutData); + + if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { + //Skip last 2 bytes in cborData, it contains status. + std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), + true); + if (item != nullptr) { + /*Ignore inputConsumed from javacard SE since HAL consumes all the input */ + //cborConverter_.getUint64(item, 1, inputConsumed); + if(outParams.size() == 0) + cborConverter_.getKeyParameters(item, 2, outParams); + cborConverter_.getBinaryArray(item, 3, tempOut); + } } + return errorCode; + }; + if(ErrorCode::OK == (errorCode = oprCtx_->update(operationHandle, std::vector(input), + sendDataCallback))) { + /* Consumed all the input */ + inputConsumed = input.size(); + output = tempOut; } } _hidl_cb(errorCode, inputConsumed, outParams, output); @@ -854,29 +871,56 @@ Return JavacardKeymaster4Device::finish(uint64_t operationHandle, const hi outParams = kmParamSet2Hidl(response.output_params); output = kmBuffer2hidlVec(response.output); } else if (response.error == KM_ERROR_INVALID_OPERATION_HANDLE) { - cppbor::Array array; - std::unique_ptr item; - std::vector cborOutData; - - // Convert input data to cbor format - array.add(operationHandle); - cborConverter_.addKeyparameters(array, inParams); - array.add(std::vector(input)); - array.add(std::vector(signature)); - cborConverter_.addHardwareAuthToken(array, authToken); - cborConverter_.addVerificationToken(array, verificationToken); - std::vector cborData = array.encode(); - - errorCode = sendData(this, pTransportFactory, Instruction::INS_FINISH_OPERATION_CMD, cborData, cborOutData); - - if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { - //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), - true); - if (item != nullptr) { - cborConverter_.getKeyParameters(item, 1, outParams); - cborConverter_.getBinaryArray(item, 2, output); + std::vector tempOut; + /* OperationContext calls this below sendDataCallback callback function. This callback + * may be called multiple times if the input data is larger than MAX_ALLOWED_INPUT_SIZE. + * This callback function decides whether to call update/finish instruction based on the + * input received from the OperationContext through finish variable. + * if finish variable is false update instruction is called, if it is true finish instruction + * is called. + */ + auto sendDataCallback = [&](std::vector& data, bool finish) -> ErrorCode { + cppbor::Array array; + Instruction ins; + std::unique_ptr item; + std::vector cborOutData; + int keyParamPos, outputPos; + + // Convert input data to cbor format + array.add(operationHandle); + cborConverter_.addKeyparameters(array, inParams); + array.add(data); + if(finish) { + array.add(std::vector(signature)); + ins = Instruction::INS_FINISH_OPERATION_CMD; + keyParamPos = 1; + outputPos = 2; + } else { + ins = Instruction::INS_UPDATE_OPERATION_CMD; + keyParamPos = 2; + outputPos = 3; } + cborConverter_.addHardwareAuthToken(array, authToken); + cborConverter_.addVerificationToken(array, verificationToken); + std::vector cborData = array.encode(); + + errorCode = sendData(this, pTransportFactory, ins, cborData, cborOutData); + + if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { + //Skip last 2 bytes in cborData, it contains status. + std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), + true); + if (item != nullptr) { + if(outParams.size() == 0) + cborConverter_.getKeyParameters(item, keyParamPos, outParams); + cborConverter_.getBinaryArray(item, outputPos, tempOut); + } + } + return errorCode; + }; + if(ErrorCode::OK == (errorCode = oprCtx_->finish(operationHandle, std::vector(input), + sendDataCallback))) { + output = tempOut; } } _hidl_cb(errorCode, outParams, output); @@ -900,6 +944,8 @@ Return JavacardKeymaster4Device::abort(uint64_t operationHandle) { std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), true); } + /* Delete the entry on this operationHandle */ + oprCtx_->clearOperationData(operationHandle); return errorCode; } diff --git a/HAL/keymaster/4.1/JavacardOperationContext.cpp b/HAL/keymaster/4.1/JavacardOperationContext.cpp index 185960d0..57d5af5e 100644 --- a/HAL/keymaster/4.1/JavacardOperationContext.cpp +++ b/HAL/keymaster/4.1/JavacardOperationContext.cpp @@ -32,6 +32,35 @@ enum class Operation { Finish = 1 }; +inline ErrorCode hidlParamSet2OperatinInfo(const hidl_vec& params, OperationInfo& info) { + for(int i = 0; i < params.size(); i++) { + const KeyParameter ¶m = params[i]; + switch(param.tag) { + case Tag::ALGORITHM: + info.alg = static_cast(param.f.integer); + break; + case Tag::DIGEST: + info.digest = static_cast(param.f.integer); + break; + case Tag::PADDING: + info.pad = static_cast(param.f.integer); + break; + default: + continue; + } + } + return ErrorCode::OK; +} + +ErrorCode OperationContext::setOperationInfo(uint64_t operationHandle, KeyPurpose purpose, const hidl_vec& params) { + ErrorCode errorCode = ErrorCode::OK; + OperationInfo info; + if(ErrorCode::OK != (errorCode = hidlParamSet2OperatinInfo(params, info))) { + return errorCode; + } + info.purpose = purpose; + return setOperationInfo(operationHandle, info); +} ErrorCode OperationContext::setOperationInfo(uint64_t operationHandle, OperationInfo& operInfo) { OperationData data; @@ -57,7 +86,7 @@ ErrorCode OperationContext::clearOperationData(uint64_t operHandle) { return ErrorCode::OK; } -ErrorCode OperationContext::validateInputData(uint64_t operHandle, Operation opr, std::vector& actualInput, std::vector& input) { +ErrorCode OperationContext::validateInputData(uint64_t operHandle, Operation opr, const std::vector& actualInput, std::vector& input) { ErrorCode errorCode = ErrorCode::OK; OperationData oprData; @@ -92,7 +121,7 @@ ErrorCode OperationContext::validateInputData(uint64_t operHandle, Operation opr return errorCode; } -ErrorCode OperationContext::update(uint64_t operHandle, std::vector& actualInput, sendDataToSE_cb cb) { +ErrorCode OperationContext::update(uint64_t operHandle, const std::vector& actualInput, sendDataToSE_cb cb) { ErrorCode errorCode = ErrorCode::OK; std::vector input; @@ -129,7 +158,7 @@ ErrorCode OperationContext::update(uint64_t operHandle, std::vector& ac return errorCode; } -ErrorCode OperationContext::finish(uint64_t operHandle, std::vector& actualInput, sendDataToSE_cb cb) { +ErrorCode OperationContext::finish(uint64_t operHandle, const std::vector& actualInput, sendDataToSE_cb cb) { ErrorCode errorCode = ErrorCode::OK; std::vector input; OperationData oprData; @@ -169,12 +198,10 @@ ErrorCode OperationContext::finish(uint64_t operHandle, std::vector& ac return errorCode; } - /* Send if any buffered data is remaining */ - if(oprData.data.buf_len > 0) { - if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, nullptr, 0, - Operation::Finish, cb))) { - return errorCode; - } + /* Send if any buffered data is remaining or to call finish */ + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, nullptr, 0, + Operation::Finish, cb, true))) { + return errorCode; } return errorCode; } diff --git a/HAL/keymaster/include/JavacardKeymaster4Device.h b/HAL/keymaster/include/JavacardKeymaster4Device.h index 6d0be552..95299956 100644 --- a/HAL/keymaster/include/JavacardKeymaster4Device.h +++ b/HAL/keymaster/include/JavacardKeymaster4Device.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace keymaster { namespace V4_1 { @@ -94,6 +95,7 @@ class JavacardKeymaster4Device : public IKeymasterDevice { private: std::unique_ptr<::keymaster::AndroidKeymaster> softKm_; + std::unique_ptr oprCtx_; bool setUpBootParams; }; diff --git a/HAL/keymaster/include/JavacardOperationContext.h b/HAL/keymaster/include/JavacardOperationContext.h index a1763650..c784b1fe 100644 --- a/HAL/keymaster/include/JavacardOperationContext.h +++ b/HAL/keymaster/include/JavacardOperationContext.h @@ -27,13 +27,16 @@ namespace keymaster { namespace V4_1 { namespace javacard { +using ::android::hardware::hidl_vec; using ::android::hardware::keymaster::V4_0::ErrorCode; using ::android::hardware::keymaster::V4_0::Algorithm; using ::android::hardware::keymaster::V4_0::KeyPurpose; using ::android::hardware::keymaster::V4_0::Digest; using ::android::hardware::keymaster::V4_0::PaddingMode; +using ::android::hardware::keymaster::V4_0::KeyParameter; +using ::android::hardware::keymaster::V4_0::Tag; -using sendDataToSE_cb = std::function& data)>; +using sendDataToSE_cb = std::function& data, bool finish)>; enum class Operation; @@ -60,10 +63,11 @@ class OperationContext { OperationContext(){} ~OperationContext() {} ErrorCode setOperationInfo(uint64_t operationHandle, OperationInfo& oeprInfo); + ErrorCode setOperationInfo(uint64_t operationHandle, KeyPurpose purpose, const hidl_vec& params); ErrorCode getOperationInfo(uint64_t operHandle, OperationInfo& operInfo); ErrorCode clearOperationData(uint64_t operationHandle); - ErrorCode update(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb); - ErrorCode finish(uint64_t operHandle, std::vector& input, sendDataToSE_cb cb); + ErrorCode update(uint64_t operHandle, const std::vector& input, sendDataToSE_cb cb); + ErrorCode finish(uint64_t operHandle, const std::vector& input, sendDataToSE_cb cb); private: std::map operationTable; @@ -77,12 +81,12 @@ class OperationContext { return ErrorCode::INVALID_OPERATION_HANDLE; } - ErrorCode validateInputData(uint64_t operHandle, Operation opr, std::vector& actualInput, + ErrorCode validateInputData(uint64_t operHandle, Operation opr, const std::vector& actualInput, std::vector& input); ErrorCode internalUpdate(uint64_t operHandle, uint8_t* input, size_t input_len, Operation opr, std::vector& out); inline ErrorCode handleInternalUpdate(uint64_t operHandle, uint8_t* data, size_t len, Operation opr, - sendDataToSE_cb cb) { + sendDataToSE_cb cb, bool finish=false) { ErrorCode errorCode = ErrorCode::OK; std::vector out; OperationData oprData; @@ -98,11 +102,11 @@ class OperationContext { } } else { /* Other algorithms no buffering required */ - for(int i = 0; i < len; i++) { + for(size_t i = 0; i < len; i++) { out.push_back(data[i]); } } - if(ErrorCode::OK != (errorCode = cb(out))) { + if(ErrorCode::OK != (errorCode = cb(out, finish))) { return errorCode; } return errorCode; From e9921a8e05131900ec192336cab0257b73123eda Mon Sep 17 00:00:00 2001 From: BKSSM Venkateswarlu Date: Mon, 15 Jun 2020 23:14:27 +0530 Subject: [PATCH 7/8] decode parse wrapped keyblob in importWrappedKey --- .../4.1/JavacardKeymaster4Device.cpp | 109 +++++++++++++----- 1 file changed, 82 insertions(+), 27 deletions(-) diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index c9ebb70f..cf16894b 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include @@ -200,6 +202,42 @@ inline hidl_vec kmBuffer2hidlVec(const ::keymaster::Buffer& buf) { return result; } +static inline void blob2Vec(const uint8_t *from, size_t size, std::vector& to) { + for(int i = 0; i < size; ++i) { + to.push_back(from[i]); + } +} + +static inline ErrorCode parseWrappedKey(const hidl_vec& wrappedKeyData, std::vector& iv, std::vector& transitKey, +std::vector& secureKey, std::vector& tag, hidl_vec& authList, KeyFormat& +keyFormat, std::vector& wrappedKeyDescription) { + KeymasterBlob kmIv; + KeymasterKeyBlob kmTransitKey; + KeymasterKeyBlob kmSecureKey; + KeymasterBlob kmTag; + AuthorizationSet authSet; + keymaster_key_format_t kmKeyFormat; + KeymasterBlob kmWrappedKeyDescription; + KeymasterKeyBlob kmWrappedKeyData; + + kmWrappedKeyData.key_material = dup_buffer(wrappedKeyData.data(), wrappedKeyData.size()); + + keymaster_error_t error = parse_wrapped_key(kmWrappedKeyData, &kmIv, &kmTransitKey, + &kmSecureKey, &kmTag, &authSet, + &kmKeyFormat, &kmWrappedKeyDescription); + if (error != KM_ERROR_OK) return legacy_enum_conversion(error); + blob2Vec(kmIv.data, kmIv.data_length, iv); + blob2Vec(kmTransitKey.key_material, kmTransitKey.key_material_size, transitKey); + blob2Vec(kmSecureKey.key_material, kmSecureKey.key_material_size, secureKey); + blob2Vec(kmTag.data, kmTag.data_length, tag); + authList = kmParamSet2Hidl(authSet); + keyFormat = static_cast(kmKeyFormat); + blob2Vec(kmWrappedKeyDescription.data, kmWrappedKeyDescription.data_length, wrappedKeyDescription); + + return ErrorCode::OK; +} + + JavacardKeymaster4Device::JavacardKeymaster4Device(): softKm_(new ::keymaster::AndroidKeymaster( []() -> auto { auto context = new JavaCardSoftKeymasterContext(); @@ -508,31 +546,31 @@ Return JavacardKeymaster4Device::importKey(const hidl_vec& k return Void(); } - cppbor::Array array; - std::unique_ptr item; - hidl_vec keyBlob; - std::vector cborOutData; - ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; - KeyCharacteristics keyCharacteristics; - - cborConverter_.addKeyparameters(array, keyParams); - array.add(static_cast(KeyFormat::RAW)); //PKCS8 is already converted to RAW - array.add(std::vector(inKey)); - std::vector cborData = array.encode(); - - errorCode = sendData(this, pTransportFactory, Instruction::INS_IMPORT_KEY_CMD, cborData, cborOutData); - - if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { - //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), - true); - if (item != nullptr) { - cborConverter_.getBinaryArray(item, 1, keyBlob); - cborConverter_.getKeyCharacteristics(item, 2, keyCharacteristics); - } - } - _hidl_cb(errorCode, keyBlob, keyCharacteristics); - return Void(); + cppbor::Array array; + std::unique_ptr item; + hidl_vec keyBlob; + std::vector cborOutData; + ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; + KeyCharacteristics keyCharacteristics; + + cborConverter_.addKeyparameters(array, keyParams); + array.add(static_cast(KeyFormat::RAW)); //PKCS8 is already converted to RAW + array.add(std::vector(inKey)); + std::vector cborData = array.encode(); + + errorCode = sendData(this, pTransportFactory, Instruction::INS_IMPORT_KEY_CMD, cborData, cborOutData); + + if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { + //Skip last 2 bytes in cborData, it contains status. + std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborOutData.begin(), cborOutData.end()-2), + true); + if (item != nullptr) { + cborConverter_.getBinaryArray(item, 1, keyBlob); + cborConverter_.getKeyCharacteristics(item, 2, keyCharacteristics); + } + } + _hidl_cb(errorCode, keyBlob, keyCharacteristics); + return Void(); } Return JavacardKeymaster4Device::importWrappedKey(const hidl_vec& wrappedKeyData, const hidl_vec& wrappingKeyBlob, const hidl_vec& maskingKey, const hidl_vec& unwrappingParams, uint64_t passwordSid, uint64_t biometricSid, importWrappedKey_cb _hidl_cb) { @@ -542,8 +580,25 @@ Return JavacardKeymaster4Device::importWrappedKey(const hidl_vec& std::vector cborOutData; ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; KeyCharacteristics keyCharacteristics; - - array.add(std::vector(wrappedKeyData)); + std::vector iv; + std::vector transitKey; + std::vector secureKey; + std::vector tag; + hidl_vec authList; + KeyFormat keyFormat; + std::vector wrappedKeyDescription; + + if(ErrorCode::OK != (errorCode = parseWrappedKey(wrappedKeyData, iv, transitKey, secureKey, + tag, authList, keyFormat, wrappedKeyDescription))) { + _hidl_cb(errorCode, keyBlob, keyCharacteristics); + return Void(); + } + array.add(transitKey); + array.add(iv); + array.add(static_cast(keyFormat)); + cborConverter_.addKeyparameters(array, authList); + array.add(secureKey); + array.add(tag); array.add(std::vector(wrappingKeyBlob)); array.add(std::vector(maskingKey)); cborConverter_.addKeyparameters(array, unwrappingParams); From ba78d68f383e8eda598bd8a0ad0ca883b27afaa6 Mon Sep 17 00:00:00 2001 From: BKSSM Venkateswarlu Date: Wed, 17 Jun 2020 20:53:43 +0530 Subject: [PATCH 8/8] 1. validations for sign and encrypt for Digest::None case 2. Fix the issue in cbor for HardwareAuthToken and VerificationToken. --- HAL/keymaster/4.1/CborConverter.cpp | 26 +++++----- .../4.1/JavacardKeymaster4Device.cpp | 6 +++ .../4.1/JavacardOperationContext.cpp | 34 ++++++++----- .../include/JavacardOperationContext.h | 49 ++++++++++++++++--- 4 files changed, 83 insertions(+), 32 deletions(-) diff --git a/HAL/keymaster/4.1/CborConverter.cpp b/HAL/keymaster/4.1/CborConverter.cpp index b54b9337..c0643ed8 100644 --- a/HAL/keymaster/4.1/CborConverter.cpp +++ b/HAL/keymaster/4.1/CborConverter.cpp @@ -297,22 +297,26 @@ bool CborConverter::getHmacSharingParameters(const std::unique_ptr& item, bool CborConverter::addVerificationToken(Array& array, const VerificationToken& verificationToken) { - array.add(verificationToken.challenge); - array.add(verificationToken.timestamp); - addKeyparameters(array, verificationToken.parametersVerified); - array.add(static_cast(verificationToken.securityLevel)); - array.add((std::vector(verificationToken.mac))); + Array vToken; + vToken.add(verificationToken.challenge); + vToken.add(verificationToken.timestamp); + addKeyparameters(vToken, verificationToken.parametersVerified); + vToken.add(static_cast(verificationToken.securityLevel)); + vToken.add((std::vector(verificationToken.mac))); + array.add(std::move(vToken)); return true; } bool CborConverter::addHardwareAuthToken(Array& array, const HardwareAuthToken& authToken) { - array.add(authToken.challenge); - array.add(authToken.userId); - array.add(authToken.authenticatorId); - array.add(static_cast(authToken.authenticatorType)); - array.add(authToken.timestamp); - array.add((std::vector(authToken.mac))); + Array hwAuthToken; + hwAuthToken.add(authToken.challenge); + hwAuthToken.add(authToken.userId); + hwAuthToken.add(authToken.authenticatorId); + hwAuthToken.add(static_cast(authToken.authenticatorType)); + hwAuthToken.add(authToken.timestamp); + hwAuthToken.add((std::vector(authToken.mac))); + array.add(std::move(hwAuthToken)); return true; } diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index cf16894b..ef1e4f04 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -904,6 +904,10 @@ Return JavacardKeymaster4Device::update(uint64_t operationHandle, const hi output = tempOut; } } + if(ErrorCode::OK != errorCode) { + /* Delete the entry on this operationHandle */ + oprCtx_->clearOperationData(operationHandle); + } _hidl_cb(errorCode, inputConsumed, outParams, output); return Void(); } @@ -978,6 +982,8 @@ Return JavacardKeymaster4Device::finish(uint64_t operationHandle, const hi output = tempOut; } } + /* Delete the entry on this operationHandle */ + oprCtx_->clearOperationData(operationHandle); _hidl_cb(errorCode, outParams, output); return Void(); } diff --git a/HAL/keymaster/4.1/JavacardOperationContext.cpp b/HAL/keymaster/4.1/JavacardOperationContext.cpp index 57d5af5e..0e1de44c 100644 --- a/HAL/keymaster/4.1/JavacardOperationContext.cpp +++ b/HAL/keymaster/4.1/JavacardOperationContext.cpp @@ -22,6 +22,8 @@ #define DES_BLOCK_SIZE 8 #define RSA_INPUT_MSG_LEN 245 /*(256-11)*/ #define EC_INPUT_MSG_LEN 32 +#define MAX_RSA_BUFFER_SIZE 256 +#define MAX_EC_BUFFER_SIZE 32 namespace keymaster { namespace V4_1 { @@ -94,20 +96,31 @@ ErrorCode OperationContext::validateInputData(uint64_t operHandle, Operation opr return errorCode; } - if(Algorithm::RSA == oprData.info.alg && Digest::NONE == oprData.info.digest) { - if(actualInput.size() > RSA_INPUT_MSG_LEN) - return ErrorCode::INVALID_INPUT_LENGTH; - } else if(Algorithm::EC == oprData.info.alg && Digest::NONE == oprData.info.digest) { - if(actualInput.size() > EC_INPUT_MSG_LEN) { + if(KeyPurpose::SIGN == oprData.info.purpose) { + if(Algorithm::RSA == oprData.info.alg && Digest::NONE == oprData.info.digest) { + if((oprData.data.buf_len+actualInput.size()) > RSA_INPUT_MSG_LEN) + return ErrorCode::INVALID_INPUT_LENGTH; + } else if(Algorithm::EC == oprData.info.alg && Digest::NONE == oprData.info.digest) { /* Silently truncate the input */ - for(int i=0; i < EC_INPUT_MSG_LEN; i++) { - input.push_back(actualInput[i]); + if(oprData.data.buf_len >= EC_INPUT_MSG_LEN) { + return ErrorCode::OK; + } else if(actualInput.size()+oprData.data.buf_len > EC_INPUT_MSG_LEN) { + for(int i=oprData.data.buf_len,j=0; i < EC_INPUT_MSG_LEN; ++i,++j) { + input.push_back(actualInput[j]); + } + return ErrorCode::OK; } - return errorCode; + } + } + + if(KeyPurpose::DECRYPT == oprData.info.purpose && Algorithm::RSA == oprData.info.alg) { + if((oprData.data.buf_len+actualInput.size()) > MAX_RSA_BUFFER_SIZE) { + return ErrorCode::INVALID_INPUT_LENGTH; } } if(opr == Operation::Finish) { + if(oprData.info.pad == PaddingMode::NONE && oprData.info.alg == Algorithm::AES) { if(((oprData.data.buf_len+actualInput.size()) % AES_BLOCK_SIZE) != 0) return ErrorCode::INVALID_INPUT_LENGTH; @@ -161,7 +174,6 @@ ErrorCode OperationContext::update(uint64_t operHandle, const std::vector& actualInput, sendDataToSE_cb cb) { ErrorCode errorCode = ErrorCode::OK; std::vector input; - OperationData oprData; /* Validate the input data */ if(ErrorCode::OK != (errorCode = validateInputData(operHandle, Operation::Update, actualInput, input))) { @@ -194,10 +206,6 @@ ErrorCode OperationContext::finish(uint64_t operHandle, const std::vector #include -#define MAX_BUF_SIZE 32 +#define MAX_BUF_SIZE 256 namespace keymaster { namespace V4_1 { @@ -85,7 +85,7 @@ class OperationContext { std::vector& input); ErrorCode internalUpdate(uint64_t operHandle, uint8_t* input, size_t input_len, Operation opr, std::vector& out); - inline ErrorCode handleInternalUpdate(uint64_t operHandle, uint8_t* data, size_t len, Operation opr, + ErrorCode handleInternalUpdate(uint64_t operHandle, uint8_t* data, size_t len, Operation opr, sendDataToSE_cb cb, bool finish=false) { ErrorCode errorCode = ErrorCode::OK; std::vector out; @@ -100,15 +100,48 @@ class OperationContext { opr, out))) { return errorCode; } + + if(ErrorCode::OK != (errorCode = cb(out, finish))) { + return errorCode; + } } else { - /* Other algorithms no buffering required */ - for(size_t i = 0; i < len; i++) { - out.push_back(data[i]); + if(oprData.info.digest == Digest::NONE) { + if(finish) { + for(int i = 0; i < oprData.data.buf_len; ++i) { + out[i] = oprData.data.buf[i]; + } + if(ErrorCode::OK != (errorCode = cb(out, finish))) { + return errorCode; + } + } else { + /* For RSA/EC algorithms just do buffering, don't send data to SE in update. + * input message length should not be more than the MAX_BUF_SIZE. + */ + if(oprData.data.buf_len <= MAX_BUF_SIZE) { + size_t bufIndex = oprData.data.buf_len; + size_t pos = 0; + for(; (pos < len) && (pos < (MAX_BUF_SIZE-bufIndex)); pos++) + { + oprData.data.buf[bufIndex+pos] = data[pos]; + } + oprData.data.buf_len += pos; + } + } + } else { + for(size_t j=0; j < len; ++j) + { + out[j] = data[j]; + } + /* if len=0, then no need to call the callback, since there is no information to be send to javacard, + * but if finish flag is true irrespective of len callback should be called. + */ + if(len != 0 || finish) { + if(ErrorCode::OK != (errorCode = cb(out, finish))) { + return errorCode; + } + } } } - if(ErrorCode::OK != (errorCode = cb(out, finish))) { - return errorCode; - } return errorCode; } };