From ce941b7dcc919153abd561bfcdf646e4e47ba446 Mon Sep 17 00:00:00 2001 From: BKSSM Venkateswarlu Date: Thu, 20 Aug 2020 01:30:42 +0530 Subject: [PATCH 1/2] For AES GCM Decryption operation hold last 16 bytes of data in update operation and send that in finish operation. In begin operation call getKeyCharacteristics to validate the keyblob and also to get keyCharacteristics. --- .../4.1/JavacardKeymaster4Device.cpp | 27 +++++++++++++------ .../4.1/JavacardOperationContext.cpp | 10 ++++--- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index fa89ad8c..240da912 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -1085,16 +1085,27 @@ Return JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec< cborConverter_.addHardwareAuthToken(array, authToken); std::vector cborData = array.encode(); - /* keyCharacteristics.hardwareEnforced is required to store algorithm, digest and padding values in operationInfo - * structure. To retrieve keyCharacteristics.hardwareEnforced, parse the keyBlob. - */ - /* TODO if keyBlob is corrupted it crashes in cbor */ - std::tie(blobItem, errorCode) = cborConverter_.decodeData(std::vector(keyBlob), false); + // keyCharacteristics.hardwareEnforced is required to store algorithm, digest and padding values in operationInfo + // structure. To retrieve keyCharacteristics.hardwareEnforced, call getKeyCharacateristics. + // By calling getKeyCharacateristics also helps in finding a corrupted keyblob. + hidl_vec applicationId; + hidl_vec applicationData; + if(getTag(inParams, Tag::APPLICATION_ID, param)) { + applicationId = param.blob; + } + if(getTag(inParams, Tag::APPLICATION_DATA, param)) { + applicationData = param.blob; + } + //Call to getKeyCharacteristics. + getKeyCharacteristics(keyBlob, applicationId, applicationData, + [&](ErrorCode error, KeyCharacteristics keyChars) { + errorCode = error; + keyCharacteristics = keyChars; + }); - if(blobItem != nullptr) { + if(errorCode == ErrorCode::OK) { errorCode = ErrorCode::UNKNOWN_ERROR; - if(cborConverter_.getKeyCharacteristics(blobItem, 3, keyCharacteristics) && - getTag(keyCharacteristics.hardwareEnforced, Tag::ALGORITHM, param)) { + if(getTag(keyCharacteristics.hardwareEnforced, Tag::ALGORITHM, param)) { errorCode = sendData(Instruction::INS_BEGIN_OPERATION_CMD, cborData, cborOutData); if((errorCode == ErrorCode::OK) && (cborOutData.size() > 2)) { //Skip last 2 bytes in cborData, it contains status. diff --git a/HAL/keymaster/4.1/JavacardOperationContext.cpp b/HAL/keymaster/4.1/JavacardOperationContext.cpp index 6b43790e..bea270c9 100644 --- a/HAL/keymaster/4.1/JavacardOperationContext.cpp +++ b/HAL/keymaster/4.1/JavacardOperationContext.cpp @@ -229,12 +229,14 @@ ErrorCode OperationContext::getBlockAlignedData(uint64_t operHandle, uint8_t* in /*Update */ //Calculate the block sized length on combined input of both buffered data and input data. uint32_t blockAlignedLen = ((data.buf_len + input_len)/blockSize) * blockSize; - //For symmetric ciphers, decryption operation and PKCS7 padding mode save last 16 bytes of block and send this - //block in finish operation. This is done to make sure that there will be always a 16 bytes data to finish - //operation so that javacard Applet may remove PKCS7 padding if any. + //For symmetric ciphers, decryption operation and PKCS7 padding mode or AES GCM operation save the last 16 bytes + //of block and send this block in finish operation. This is done to make sure that there will be always a 16 + //bytes of data left for finish operation so that javacard Applet may remove PKCS7 padding if any or get the tag + //data for AES GCM operation for authentication purpose. if(((operationTable[operHandle].info.alg == Algorithm::AES) || (operationTable[operHandle].info.alg == Algorithm::TRIPLE_DES)) && - (operationTable[operHandle].info.pad == PaddingMode::PKCS7) && + (operationTable[operHandle].info.pad == PaddingMode::PKCS7 || + operationTable[operHandle].info.mode == BlockMode::GCM) && (operationTable[operHandle].info.purpose == KeyPurpose::DECRYPT)) { if(blockAlignedLen >= blockSize) blockAlignedLen -= blockSize; } From abe43e7504ede7ac3cf55bb4dfc06c0f11b15db3 Mon Sep 17 00:00:00 2001 From: BKSSM Venkateswarlu Date: Sun, 23 Aug 2020 03:15:06 +0530 Subject: [PATCH 2/2] 1. Sending masterkey in provision commandi. 2. Fixed the issue in buffer logic. --- .../4.1/JavacardKeymaster4Device.cpp | 5 +++ .../4.1/JavacardOperationContext.cpp | 33 ++++++++++++------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index 240da912..4204a8d7 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -52,6 +52,8 @@ namespace keymaster { namespace V4_1 { namespace javacard { +//This key is used as master key for computing Hmac shared secret. +constexpr uint8_t kFakeKeyAgreementKey[32] = {}; static std::unique_ptr pTransportFactory = nullptr; constexpr size_t kOperationTableSize = 4; @@ -439,6 +441,8 @@ ErrorCode JavacardKeymaster4Device::provision(const hidl_vec& keyP std::vector subject; std::vector authorityKeyIdentifier; std::vector notAfter; + std::vector masterKey(kFakeKeyAgreementKey, kFakeKeyAgreementKey + + sizeof(kFakeKeyAgreementKey)/sizeof(kFakeKeyAgreementKey[0])); /* Subject, AuthorityKeyIdentifier and Expirty time of the root certificate are required by javacard. */ /* Get X509 certificate instance for the root certificate.*/ @@ -467,6 +471,7 @@ ErrorCode JavacardKeymaster4Device::provision(const hidl_vec& keyP array.add(subject); array.add(notAfter); array.add(authorityKeyIdentifier); + array.add(masterKey); std::vector cborData = array.encode(); if(ErrorCode::OK != (errorCode = constructApduMessage(ins, cborData, apdu))) diff --git a/HAL/keymaster/4.1/JavacardOperationContext.cpp b/HAL/keymaster/4.1/JavacardOperationContext.cpp index bea270c9..457a6d87 100644 --- a/HAL/keymaster/4.1/JavacardOperationContext.cpp +++ b/HAL/keymaster/4.1/JavacardOperationContext.cpp @@ -16,6 +16,7 @@ */ #include +#include #define MAX_ALLOWED_INPUT_SIZE 512 #define AES_BLOCK_SIZE 16 @@ -203,12 +204,12 @@ ErrorCode OperationContext::finish(uint64_t operHandle, const std::vector& out) { - int dataToSELen = 0; - int inputConsumed = 0;/*Length of the data consumed from input */ - int blockSize = 0; + size_t dataToSELen = 0; + 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; @@ -228,7 +229,7 @@ ErrorCode OperationContext::getBlockAlignedData(uint64_t operHandle, uint8_t* in } else { /*Update */ //Calculate the block sized length on combined input of both buffered data and input data. - uint32_t blockAlignedLen = ((data.buf_len + input_len)/blockSize) * blockSize; + size_t blockAlignedLen = ((data.buf_len + input_len)/blockSize) * blockSize; //For symmetric ciphers, decryption operation and PKCS7 padding mode or AES GCM operation save the last 16 bytes //of block and send this block in finish operation. This is done to make sure that there will be always a 16 //bytes of data left for finish operation so that javacard Applet may remove PKCS7 padding if any or get the tag @@ -242,7 +243,7 @@ ErrorCode OperationContext::getBlockAlignedData(uint64_t operHandle, uint8_t* in } //Copy data to be send to SE from buffer, only if atleast a minimum block aligned size is available. if(blockAlignedLen >= blockSize) { - for(size_t pos = 0; pos < data.buf_len; pos++) { + for(size_t pos = 0; pos < std::min(blockAlignedLen, data.buf_len); pos++) { out.push_back(data.buf[pos]); } } @@ -250,7 +251,9 @@ ErrorCode OperationContext::getBlockAlignedData(uint64_t operHandle, uint8_t* in } if(dataToSELen > 0) { - inputConsumed = dataToSELen - data.buf_len; + //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. + inputConsumed = (data.buf_len > dataToSELen) ? 0 : (dataToSELen - data.buf_len); //Copy the buffer to be send to SE. for(int i = 0; i < inputConsumed; i++) @@ -258,10 +261,18 @@ ErrorCode OperationContext::getBlockAlignedData(uint64_t operHandle, uint8_t* in 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; + if(data.buf_len > dataToSELen) { + //Only blockAlignedLen data is consumed from buffer so reorder the buffer data. + memcpy(data.buf, data.buf+dataToSELen, data.buf_len-dataToSELen); + memset(data.buf+dataToSELen, 0x00, data.buf_len-dataToSELen); + data.buf_len -= dataToSELen; + bufIndex = data.buf_len; + } else { + // 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; + } } }