Skip to content
This repository was archived by the owner on May 24, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions HAL/keymaster/4.1/JavacardKeymaster4Device.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -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<se_transport::TransportFactory> pTransportFactory = nullptr;
constexpr size_t kOperationTableSize = 4;
Expand DownExpand Up@@ -439,6 +441,8 @@ ErrorCode JavacardKeymaster4Device::provision(const hidl_vec<KeyParameter>& keyP
std::vector<uint8_t> subject;
std::vector<uint8_t> authorityKeyIdentifier;
std::vector<uint8_t> notAfter;
std::vector<uint8_t> 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.*/
Expand DownExpand Up@@ -467,6 +471,7 @@ ErrorCode JavacardKeymaster4Device::provision(const hidl_vec<KeyParameter>& keyP
array.add(subject);
array.add(notAfter);
array.add(authorityKeyIdentifier);
array.add(masterKey);
std::vector<uint8_t> cborData = array.encode();

if(ErrorCode::OK != (errorCode = constructApduMessage(ins, cborData, apdu)))
Expand DownExpand Up@@ -1085,16 +1090,27 @@ Return<void> JavacardKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec<
cborConverter_.addHardwareAuthToken(array, authToken);
std::vector<uint8_t> 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<uint8_t>(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<uint8_t> applicationId;
hidl_vec<uint8_t> 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.
Expand Down
43 changes: 28 additions & 15 deletions HAL/keymaster/4.1/JavacardOperationContext.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,7 @@
*/

#include <JavacardOperationContext.h>
#include <algorithm>

#define MAX_ALLOWED_INPUT_SIZE 512
#define AES_BLOCK_SIZE 16
Expand DownExpand Up@@ -203,12 +204,12 @@ ErrorCode OperationContext::finish(uint64_t operHandle, const std::vector<uint8_
return errorCode;
}

/* This function is called for only symmetric operations */
/* This function is called for only Symmetric operations */
ErrorCode OperationContext::getBlockAlignedData(uint64_t operHandle, uint8_t* input, size_t input_len,
Operation opr, std::vector<uint8_t>& 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;

Expand All@@ -228,38 +229,50 @@ 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;
//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.
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
//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;
}
//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]);
}
}
dataToSELen = blockAlignedLen;
}

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++)
{
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;
}
}
}

Expand Down