diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index 23583024..445f3737 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,8 @@ #define INS_BEGIN_KM_CMD 0x00 #define INS_END_KM_PROVISION_CMD 0x20 #define INS_END_KM_CMD 0x7F +#define SW_KM_OPR 0UL +#define SB_KM_OPR 1UL namespace keymaster { namespace V4_1 { @@ -56,6 +59,10 @@ namespace javacard { static std::unique_ptr pTransportFactory = nullptr; constexpr size_t kOperationTableSize = 4; +/* Key is the newly generated operation handle. Value is a pair with first element having + * original operation handle and second element represents SW or SB operation. + */ +std::map> operationTable; struct KM_AUTH_LIST_Delete { void operator()(KM_AUTH_LIST* p) { KM_AUTH_LIST_free(p); } @@ -116,6 +123,53 @@ static inline bool getTag(const hidl_vec& params, Tag tag, KeyPara return false; } +/* Generate new operation handle */ +static ErrorCode generateOperationHandle(uint64_t& oprHandle) { + std::map>::iterator it; + do { + keymaster_error_t err = GenerateRandom(reinterpret_cast(&oprHandle), (size_t)sizeof(oprHandle)); + if (err != KM_ERROR_OK) { + return legacy_enum_conversion(err); + } + it = operationTable.find(oprHandle); + } while (it != operationTable.end()); + return ErrorCode::OK; +} + +/* Create a new operation handle entry in operation table.*/ +static ErrorCode createOprHandleEntry(uint64_t origOprHandle, uint64_t keymasterSrc, uint64_t& newOperationHandle) { + ErrorCode errorCode = ErrorCode::OK; + if (ErrorCode::OK != (errorCode = generateOperationHandle(newOperationHandle))) { + return errorCode; + } + operationTable[newOperationHandle] = std::make_pair(origOprHandle, keymasterSrc); + return errorCode; +} + +/* Get original operation handle generated by softkeymaster/strongboxkeymaster. */ +static ErrorCode getOrigOperationHandle(uint64_t halGeneratedOperationHandle, uint64_t& origOprHandle) { + std::map>::iterator it = operationTable.find(halGeneratedOperationHandle); + if (it == operationTable.end()) { + return ErrorCode::INVALID_OPERATION_HANDLE; + } + origOprHandle = it->second.first; + return ErrorCode::OK; +} + +/* Tells if the operation handle belongs to strongbox keymaster. */ +static bool isStrongboxOperation(uint64_t halGeneratedOperationHandle) { + std::map>::iterator it = operationTable.find(halGeneratedOperationHandle); + if (it == operationTable.end()) { + return false; + } + return (SB_KM_OPR == it->second.second); +} + +/* Delete the operation handle entry from operation table. */ +static void deleteOprHandleEntry(uint64_t halGeneratedOperationHandle) { + operationTable.erase(halGeneratedOperationHandle); +} + ErrorCode encodeParametersVerified(const VerificationToken& verificationToken, std::vector& asn1ParamsVerified) { if (verificationToken.parametersVerified.size() > 0) { AuthorizationSet paramSet; @@ -304,14 +358,10 @@ Return JavacardKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_ hidl_string jcKeymasterAuthor; ErrorCode ret = sendData(Instruction::INS_GET_HW_INFO_CMD, input, resp); - if(ret != ErrorCode::OK) { - //Socket not connected. - _hidl_cb(SecurityLevel::STRONGBOX, JAVACARD_KEYMASTER_NAME, JAVACARD_KEYMASTER_AUTHOR); - return Void(); - } else { + if (ret == ErrorCode::OK) { //Skip last 2 bytes in cborData, it contains status. std::tie(item, ret) = cborConverter_.decodeData(std::vector(resp.begin(), resp.end()-2), - true); + false); if (item != nullptr) { std::vector temp; if(!cborConverter_.getUint64(item, 0, securityLevel) || @@ -323,30 +373,22 @@ Return JavacardKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_ } _hidl_cb(static_cast(securityLevel), jcKeymasterName, jcKeymasterAuthor); return Void(); + } else { + // It should not come here, but incase if for any reason SB keymaster fails to getHardwareInfo + // return proper values from HAL. + _hidl_cb(SecurityLevel::STRONGBOX, JAVACARD_KEYMASTER_NAME, JAVACARD_KEYMASTER_AUTHOR); + return Void(); } } Return JavacardKeymaster4Device::getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) { - /* TODO temporary fix: vold daemon calls performHmacKeyAgreement. At that time when vold calls this API there is no - * network connectivity and socket cannot be connected. So as a hack we are calling softkeymaster to getHmacSharing - * parameters. - */ std::vector cborData; std::vector input; std::unique_ptr item; HmacSharingParameters hmacSharingParameters; ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; errorCode = sendData(Instruction::INS_GET_HMAC_SHARING_PARAM_CMD, input, cborData); - if(errorCode != ErrorCode::OK) { - auto response = softKm_->GetHmacSharingParameters(); - ::android::hardware::keymaster::V4_0::HmacSharingParameters params; - params.seed.setToExternal(const_cast(response.params.seed.data), - response.params.seed.data_length); - static_assert(sizeof(response.params.nonce) == params.nonce.size(), "Nonce sizes don't match"); - memcpy(params.nonce.data(), response.params.nonce, params.nonce.size()); - _hidl_cb(legacy_enum_conversion(response.error), params); - return Void(); - } else { + if (ErrorCode::OK == errorCode) { //Skip last 2 bytes in cborData, it contains status. std::tie(item, errorCode) = cborConverter_.decodeData(std::vector(cborData.begin(), cborData.end()-2), true); @@ -355,16 +397,26 @@ Return JavacardKeymaster4Device::getHmacSharingParameters(getHmacSharingPa errorCode = ErrorCode::UNKNOWN_ERROR; } } - _hidl_cb(errorCode, hmacSharingParameters); - return Void(); } +#ifdef VTS_EMULATOR + /* TODO temporary fix: vold daemon calls performHmacKeyAgreement. At that time when vold calls this API there is no + * network connectivity and socket cannot be connected. So as a hack we are calling softkeymaster to getHmacSharing + * parameters. + */ + else { + auto response = softKm_->GetHmacSharingParameters(); + hmacSharingParameters.seed.setToExternal(const_cast(response.params.seed.data), + response.params.seed.data_length); + static_assert(sizeof(response.params.nonce) == hmacSharingParameters.nonce.size(), "Nonce sizes don't match"); + memcpy(hmacSharingParameters.nonce.data(), response.params.nonce, hmacSharingParameters.nonce.size()); + errorCode = legacy_enum_conversion(response.error); + } +#endif + _hidl_cb(errorCode, hmacSharingParameters); + return Void(); } Return JavacardKeymaster4Device::computeSharedHmac(const hidl_vec& params, computeSharedHmac_cb _hidl_cb) { - /* TODO temporary fix: vold daemon calls performHmacKeyAgreement. At that time when vold calls this API there is no - * network connectivity and socket cannot be connected. So as a hack we are calling softkeymaster to - * computeSharedHmac. - */ cppbor::Array array; std::unique_ptr item; std::vector cborOutData; @@ -387,7 +439,25 @@ Return JavacardKeymaster4Device::computeSharedHmac(const hidl_vec cborData = array.encode(); errorCode = sendData(Instruction::INS_COMPUTE_SHARED_HMAC_CMD, cborData, cborOutData); - if(errorCode != ErrorCode::OK) { + if (ErrorCode::OK == errorCode) { + //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) { + std::vector bstr; + if(!cborConverter_.getBinaryArray(item, 1, bstr)) { + errorCode = ErrorCode::UNKNOWN_ERROR; + } else { + sharingCheck = bstr; + } + } + } +#ifdef VTS_EMULATOR + /* TODO temporary fix: vold daemon calls performHmacKeyAgreement. At that time when vold calls this API there is no + * network connectivity and socket cannot be connected. So as a hack we are calling softkeymaster to + * computeSharedHmac. + */ + else { ComputeSharedHmacRequest request; request.params_array.params_array = new keymaster::HmacSharingParameters[params.size()]; request.params_array.num_params = params.size(); @@ -401,29 +471,13 @@ Return JavacardKeymaster4Device::computeSharedHmac(const hidl_vecComputeSharedHmac(request); - hidl_vec sharing_check; - if (response.error == KM_ERROR_OK) sharing_check = kmBlob2hidlVec(response.sharing_check); - - _hidl_cb(legacy_enum_conversion(response.error), sharing_check); - return Void(); - - } else { - //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) { - std::vector bstr; - if(!cborConverter_.getBinaryArray(item, 1, bstr)) { - errorCode = ErrorCode::UNKNOWN_ERROR; - } else { - sharingCheck = bstr; - } - } - _hidl_cb(errorCode, sharingCheck); - return Void(); + if (response.error == KM_ERROR_OK) sharingCheck = kmBlob2hidlVec(response.sharing_check); + errorCode = legacy_enum_conversion(response.error); } - -} +#endif + _hidl_cb(errorCode, sharingCheck); + return Void(); + } Return JavacardKeymaster4Device::verifyAuthorization(uint64_t , const hidl_vec& , const HardwareAuthToken& , verifyAuthorization_cb _hidl_cb) { VerificationToken verificationToken; @@ -791,12 +845,15 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< hidl_vec outParams; uint64_t operationHandle = 0; hidl_vec resultParams; + uint64_t generatedOpHandle = 0; if(keyBlob.size() == 0) { _hidl_cb(ErrorCode::INVALID_ARGUMENT, resultParams, operationHandle); return Void(); } - + /* Asymmetric public key operations like RSA Verify, RSA Encrypt, ECDSA verify + * are handled by softkeymaster. + */ if (KeyPurpose::ENCRYPT == purpose || KeyPurpose::VERIFY == purpose) { BeginOperationRequest request; request.purpose = legacy_enum_conversion(purpose); @@ -804,13 +861,21 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< request.additional_params.Reinitialize(KmParamSet(inParams)); BeginOperationResponse response; + /* For Symmetric key operation, the BeginOperation returns KM_ERROR_INCOMPATIBLE_ALGORITHM error. */ softKm_->BeginOperation(request, &response); 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); + errorCode = legacy_enum_conversion(response.error); + /* Create a new operation handle and add a entry inside the operation table map with + * key - new operation handle + * value - hal generated operation handle. + */ + if (errorCode == ErrorCode::OK) + errorCode = createOprHandleEntry(response.op_handle, SW_KM_OPR, generatedOpHandle); + _hidl_cb(errorCode, resultParams, generatedOpHandle); return Void(); } } @@ -869,29 +934,44 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< } } } - _hidl_cb(errorCode, outParams, operationHandle); + /* Create a new operation handle and add a entry inside the operation table map with + * key - new operation handle + * value - hal generated operation handle. + */ + if (ErrorCode::OK == errorCode) + errorCode = createOprHandleEntry(operationHandle, SB_KM_OPR, generatedOpHandle); + _hidl_cb(errorCode, outParams, generatedOpHandle); return Void(); } -Return JavacardKeymaster4Device::update(uint64_t operationHandle, const hidl_vec& inParams, const hidl_vec& input, const HardwareAuthToken& authToken, const VerificationToken& verificationToken, update_cb _hidl_cb) { +Return JavacardKeymaster4Device::update(uint64_t halGeneratedOprHandle, const hidl_vec& inParams, const hidl_vec& input, const HardwareAuthToken& authToken, const VerificationToken& verificationToken, update_cb _hidl_cb) { ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; - 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) { + uint64_t operationHandle; + UpdateOperationResponse response; + if (ErrorCode::OK != (errorCode = getOrigOperationHandle(halGeneratedOprHandle, operationHandle))) { + _hidl_cb(errorCode, inputConsumed, outParams, output); + return Void(); + } + + if (!isStrongboxOperation(halGeneratedOprHandle)) { + /* SW keymaster (Public key operation) */ + UpdateOperationRequest request; + request.op_handle = operationHandle; + request.input.Reinitialize(input.data(), input.size()); + request.additional_params.Reinitialize(KmParamSet(inParams)); + + softKm_->UpdateOperation(request, &response); + 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 { + /* Strongbox Keymaster operation */ 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. @@ -952,32 +1032,49 @@ Return JavacardKeymaster4Device::update(uint64_t operationHandle, const hi inputConsumed = input.size(); output = tempOut; } + if(ErrorCode::OK != errorCode) { + abort(halGeneratedOprHandle); + } } if(ErrorCode::OK != errorCode) { - abort(operationHandle); + /* Delete the entry from operation table. */ + deleteOprHandleEntry(halGeneratedOprHandle); } + _hidl_cb(errorCode, inputConsumed, outParams, output); return Void(); } -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) { +Return JavacardKeymaster4Device::finish(uint64_t halGeneratedOprHandle, const hidl_vec& inParams, const hidl_vec& input, const hidl_vec& signature, const HardwareAuthToken& authToken, const VerificationToken& verificationToken, finish_cb _hidl_cb) { 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); - + uint64_t operationHandle; 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) { + FinishOperationResponse response; + + if (ErrorCode::OK != (errorCode = getOrigOperationHandle(halGeneratedOprHandle, operationHandle))) { + _hidl_cb(errorCode, outParams, output); + return Void(); + } + + if (!isStrongboxOperation(halGeneratedOprHandle)) { + /* SW keymaster (Public key operation) */ + 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); + + errorCode = legacy_enum_conversion(response.error); + if (response.error == KM_ERROR_OK) { + outParams = kmParamSet2Hidl(response.output_params); + output = kmBuffer2hidlVec(response.output); + } + } else { + /* Strongbox Keymaster operation */ std::vector tempOut; bool aadTag = false; /* OperationContext calls this below sendDataCallback callback function. This callback @@ -1034,7 +1131,6 @@ Return JavacardKeymaster4Device::finish(uint64_t operationHandle, const hi cborConverter_.addHardwareAuthToken(array, authToken); cborConverter_.addVerificationToken(array, verificationToken, asn1ParamsVerified); std::vector cborData = array.encode(); - errorCode = sendData(ins, cborData, cborOutData); if(errorCode == ErrorCode::OK) { @@ -1061,14 +1157,23 @@ Return JavacardKeymaster4Device::finish(uint64_t operationHandle, const hi sendDataCallback))) { output = tempOut; } + if (ErrorCode::OK != errorCode) { + abort(halGeneratedOprHandle); + } } - abort(operationHandle); + /* Delete the entry from operation table. */ + deleteOprHandleEntry(halGeneratedOprHandle); + oprCtx_->clearOperationData(operationHandle); _hidl_cb(errorCode, outParams, output); return Void(); } -Return JavacardKeymaster4Device::abort(uint64_t operationHandle) { +Return JavacardKeymaster4Device::abort(uint64_t halGeneratedOprHandle) { ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; + uint64_t operationHandle; + if (ErrorCode::OK != (errorCode = getOrigOperationHandle(halGeneratedOprHandle, operationHandle))) { + return errorCode; + } AbortOperationRequest request; request.op_handle = operationHandle; @@ -1095,6 +1200,7 @@ Return JavacardKeymaster4Device::abort(uint64_t operationHandle) { } /* Delete the entry on this operationHandle */ oprCtx_->clearOperationData(operationHandle); + deleteOprHandleEntry(halGeneratedOprHandle); return errorCode; } diff --git a/HAL/keymaster/4.1/JavacardOperationContext.cpp b/HAL/keymaster/4.1/JavacardOperationContext.cpp index 457a6d87..7319cb3c 100644 --- a/HAL/keymaster/4.1/JavacardOperationContext.cpp +++ b/HAL/keymaster/4.1/JavacardOperationContext.cpp @@ -23,7 +23,6 @@ #define DES_BLOCK_SIZE 8 #define RSA_INPUT_MSG_LEN 256 #define EC_INPUT_MSG_LEN 32 -#define MAX_RSA_BUFFER_SIZE 256 #define MAX_EC_BUFFER_SIZE 32 namespace keymaster { @@ -104,11 +103,10 @@ ErrorCode OperationContext::validateInputData(uint64_t operHandle, Operation opr } if(KeyPurpose::DECRYPT == oprData.info.purpose && Algorithm::RSA == oprData.info.alg) { - if((oprData.data.buf_len+actualInput.size()) > MAX_RSA_BUFFER_SIZE) { + if((oprData.data.buf_len+actualInput.size()) > RSA_INPUT_MSG_LEN) { return ErrorCode::INVALID_INPUT_LENGTH; } } - if(opr == Operation::Finish) { //If it is observed in finish operation that buffered data + input data exceeds the MAX_ALLOWED_INPUT_SIZE then //combine both the data in a single buffer. This helps in making sure that no data is left out in the buffer after @@ -123,6 +121,7 @@ ErrorCode OperationContext::validateInputData(uint64_t operHandle, Operation opr memset(oprData.data.buf, 0x00, sizeof(oprData.data.buf)); oprData.data.buf_len = 0; } + return ErrorCode::OK; } } input = actualInput; @@ -170,7 +169,6 @@ ErrorCode OperationContext::update(uint64_t operHandle, const std::vector& actualInput, sendDataToSE_cb cb) { ErrorCode errorCode = ErrorCode::OK; std::vector input; - /* Validate the input data */ if(ErrorCode::OK != (errorCode = validateInputData(operHandle, Operation::Finish, actualInput, input))) { return errorCode; @@ -183,9 +181,18 @@ ErrorCode OperationContext::finish(uint64_t operHandle, const std::vector newInput(first, end); - if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, newInput.data(), newInput.size(), - Operation::Update, cb))) { - return errorCode; + if(extraData == 0 && (i == noOfChunks - 1)) { + //Last chunk + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, newInput.data(), newInput.size(), + Operation::Finish, cb, true))) { + return errorCode; + } + + } else { + if(ErrorCode::OK != (errorCode = handleInternalUpdate(operHandle, newInput.data(), newInput.size(), + Operation::Update, cb))) { + return errorCode; + } } } if(extraData > 0) { @@ -204,19 +211,31 @@ ErrorCode OperationContext::finish(uint64_t operHandle, const std::vector& out) { - size_t dataToSELen = 0; + size_t dataToSELen = 0;/*Length of the data to be send to the Applet.*/ size_t inputConsumed = 0;/*Length of the data consumed from input */ size_t 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; + } else { + return ErrorCode::INCOMPATIBLE_ALGORITHM; } if(opr == Operation::Finish) { @@ -253,6 +272,8 @@ ErrorCode OperationContext::getBlockAlignedData(uint64_t operHandle, uint8_t* in if(dataToSELen > 0) { //If buffer length is greater than the data length to be send to SE, then input data consumed is 0. //That means all the data to be send to SE is consumed from the buffer. + //The buffer length might become greater than dataToSELen in the cases where we are saving the last block of + //data i.e. AES/TDES Decryption with PKC7Padding or AES GCM Decryption operations. inputConsumed = (data.buf_len > dataToSELen) ? 0 : (dataToSELen - data.buf_len); //Copy the buffer to be send to SE. @@ -289,7 +310,6 @@ ErrorCode OperationContext::handleInternalUpdate(uint64_t operHandle, uint8_t* d sendDataToSE_cb cb, bool finish) { ErrorCode errorCode = ErrorCode::OK; std::vector out; - if(Algorithm::AES == operationTable[operHandle].info.alg || Algorithm::TRIPLE_DES == operationTable[operHandle].info.alg) { /*Symmetric */ @@ -331,18 +351,16 @@ ErrorCode OperationContext::handleInternalUpdate(uint64_t operHandle, uint8_t* d return errorCode; } } else { - //For strongbox keymaster, in NoDigest case the length of the input message for RSA should be more than + //For strongbox keymaster, in NoDigest case the length of the input message for RSA should not be more than //256 and for EC it should not be more than 32. This validation is already happening in - //validateInputData function. Just for safety sake we are checking the length to MAX_BUF_SIZE. - if(operationTable[operHandle].data.buf_len <= MAX_BUF_SIZE) { - size_t bufIndex = operationTable[operHandle].data.buf_len; - size_t pos = 0; - for(; (pos < len) && (pos < (MAX_BUF_SIZE-bufIndex)); pos++) - { - operationTable[operHandle].data.buf[bufIndex+pos] = data[pos]; - } - operationTable[operHandle].data.buf_len += pos; + //validateInputData function. + size_t bufIndex = operationTable[operHandle].data.buf_len; + size_t pos = 0; + for(; pos < len; ++pos) + { + operationTable[operHandle].data.buf[bufIndex+pos] = data[pos]; } + operationTable[operHandle].data.buf_len += pos; } } else { /* With Digest */ for(size_t j=0; j < len; ++j) diff --git a/HAL/keymaster/Android.bp b/HAL/keymaster/Android.bp index 8b34023d..d92809e8 100644 --- a/HAL/keymaster/Android.bp +++ b/HAL/keymaster/Android.bp @@ -49,6 +49,13 @@ cc_binary { "libjc_transport", "libcrypto", ], + product_variables: { + debuggable: { + cflags: [ + "-DVTS_EMULATOR", + ] + } + } } cc_library {