blob: d45957d7e9a3bdd3b62790ea550171c469683ff7 [file] [log] [blame]
/*
* 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.
*/
/******************************************************************************
*
* The original Work has been changed by NXP.
*
* 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.
*
* Copyright 2022 NXP
*
******************************************************************************/
#define LOG_TAG "javacard.keymint.device.strongbox-impl"
#include "JavacardKeyMintDevice.h"
#include <regex.h>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
#include <memunreachable/memunreachable.h>
#include <string>
#include <vector>
#include <KeyMintUtils.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <hardware/hw_auth_token.h>
#include <keymaster/android_keymaster_messages.h>
#include <keymaster/wrapped_key.h>
#include "JavacardKeyMintOperation.h"
#include "JavacardSharedSecret.h"
namespace aidl::android::hardware::security::keymint {
using cppbor::Bstr;
using cppbor::EncodedItem;
using cppbor::Uint;
using ::keymaster::AuthorizationSet;
using ::keymaster::dup_buffer;
using ::keymaster::KeymasterBlob;
using ::keymaster::KeymasterKeyBlob;
using ::keymint::javacard::Instruction;
using std::string;
ScopedAStatus JavacardKeyMintDevice::defaultHwInfo(KeyMintHardwareInfo* info) {
info->versionNumber = 2;
info->keyMintAuthorName = "Google";
info->keyMintName = "JavacardKeymintDevice";
info->securityLevel = securitylevel_;
info->timestampTokenRequired = true;
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
auto [item, err] = card_->sendRequest(Instruction::INS_GET_HW_INFO_CMD);
std::optional<string> optKeyMintName;
std::optional<string> optKeyMintAuthorName;
std::optional<uint64_t> optSecLevel;
std::optional<uint64_t> optVersion;
std::optional<uint64_t> optTsRequired;
if (err != KM_ERROR_OK || !(optVersion = cbor_.getUint64(item, 1)) ||
!(optSecLevel = cbor_.getUint64(item, 2)) ||
!(optKeyMintName = cbor_.getByteArrayStr(item, 3)) ||
!(optKeyMintAuthorName = cbor_.getByteArrayStr(item, 4)) ||
!(optTsRequired = cbor_.getUint64(item, 5))) {
LOG(ERROR) << "Error in response of getHardwareInfo.";
LOG(INFO) << "Returning defaultHwInfo in getHardwareInfo.";
return defaultHwInfo(info);
}
card_->initializeJavacard();
info->keyMintName = std::move(optKeyMintName.value());
info->keyMintAuthorName = std::move(optKeyMintAuthorName.value());
info->timestampTokenRequired = (optTsRequired.value() == 1);
info->securityLevel = static_cast<SecurityLevel>(std::move(optSecLevel.value()));
info->versionNumber = static_cast<int32_t>(std::move(optVersion.value()));
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::generateKey(const vector<KeyParameter>& keyParams,
const optional<AttestationKey>& attestationKey,
KeyCreationResult* creationResult) {
card_->sendPendingEvents();
cppbor::Array array;
// add key params
cbor_.addKeyparameters(array, keyParams);
// add attestation key if any
cbor_.addAttestationKey(array, attestationKey);
auto [item, err] = card_->sendRequest(Instruction::INS_GENERATE_KEY_CMD, array);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending generateKey.";
return km_utils::kmError2ScopedAStatus(err);
}
auto optKeyBlob = cbor_.getByteArrayVec(item, 1);
auto optKeyChars = cbor_.getKeyCharacteristics(item, 2);
auto optCertChain = cbor_.getCertificateChain(item, 3);
if (!optKeyBlob || !optKeyChars || !optCertChain) {
LOG(ERROR) << "Error in decoding og response in generateKey.";
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
}
creationResult->keyCharacteristics = std::move(optKeyChars.value());
creationResult->certificateChain = std::move(optCertChain.value());
creationResult->keyBlob = std::move(optKeyBlob.value());
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
cppbor::Array request;
// add key data
request.add(Bstr(data));
auto [item, err] = card_->sendRequest(Instruction::INS_ADD_RNG_ENTROPY_CMD, request);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending addRngEntropy.";
return km_utils::kmError2ScopedAStatus(err);
}
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::importKey(const vector<KeyParameter>& keyParams,
KeyFormat keyFormat, const vector<uint8_t>& keyData,
const optional<AttestationKey>& attestationKey,
KeyCreationResult* creationResult) {
card_->sendPendingEvents();
cppbor::Array request;
// add key params
cbor_.addKeyparameters(request, keyParams);
// add key format
request.add(Uint(static_cast<uint8_t>(keyFormat)));
// add key data
request.add(Bstr(keyData));
// add attestation key if any
cbor_.addAttestationKey(request, attestationKey);
auto [item, err] = card_->sendRequest(Instruction::INS_IMPORT_KEY_CMD, request);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending data in importKey.";
return km_utils::kmError2ScopedAStatus(err);
}
auto optKeyBlob = cbor_.getByteArrayVec(item, 1);
auto optKeyChars = cbor_.getKeyCharacteristics(item, 2);
auto optCertChain = cbor_.getCertificateChain(item, 3);
if (!optKeyBlob || !optKeyChars || !optCertChain) {
LOG(ERROR) << "Error in decoding response in importKey.";
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
}
creationResult->keyCharacteristics = std::move(optKeyChars.value());
creationResult->certificateChain = std::move(optCertChain.value());
creationResult->keyBlob = std::move(optKeyBlob.value());
return ScopedAStatus::ok();
}
// import wrapped key is divided into 2 stage operation.
ScopedAStatus JavacardKeyMintDevice::importWrappedKey(const vector<uint8_t>& wrappedKeyData,
const vector<uint8_t>& wrappingKeyBlob,
const vector<uint8_t>& maskingKey,
const vector<KeyParameter>& unwrappingParams,
int64_t passwordSid, int64_t biometricSid,
KeyCreationResult* creationResult) {
card_->sendPendingEvents();
cppbor::Array request;
std::unique_ptr<Item> item;
vector<uint8_t> keyBlob;
std::vector<uint8_t> response;
vector<KeyCharacteristics> keyCharacteristics;
std::vector<uint8_t> iv;
std::vector<uint8_t> transitKey;
std::vector<uint8_t> secureKey;
std::vector<uint8_t> tag;
vector<KeyParameter> authList;
KeyFormat keyFormat;
std::vector<uint8_t> wrappedKeyDescription;
keymaster_error_t errorCode = parseWrappedKey(wrappedKeyData, iv, transitKey, secureKey, tag,
authList, keyFormat, wrappedKeyDescription);
if (errorCode != KM_ERROR_OK) {
LOG(ERROR) << "Error in parse wrapped key in importWrappedKey.";
return km_utils::kmError2ScopedAStatus(errorCode);
}
// begin import
std::tie(item, errorCode) =
sendBeginImportWrappedKeyCmd(transitKey, wrappingKeyBlob, maskingKey, unwrappingParams);
if (errorCode != KM_ERROR_OK) {
LOG(ERROR) << "Error in send begin import wrapped key in importWrappedKey.";
return km_utils::kmError2ScopedAStatus(errorCode);
}
// Finish the import
std::tie(item, errorCode) = sendFinishImportWrappedKeyCmd(
authList, keyFormat, secureKey, tag, iv, wrappedKeyDescription, passwordSid, biometricSid);
if (errorCode != KM_ERROR_OK) {
LOG(ERROR) << "Error in send finish import wrapped key in importWrappedKey.";
return km_utils::kmError2ScopedAStatus(errorCode);
}
auto optKeyBlob = cbor_.getByteArrayVec(item, 1);
auto optKeyChars = cbor_.getKeyCharacteristics(item, 2);
auto optCertChain = cbor_.getCertificateChain(item, 3);
if (!optKeyBlob || !optKeyChars || !optCertChain) {
LOG(ERROR) << "Error in decoding the response in importWrappedKey.";
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
}
creationResult->keyCharacteristics = std::move(optKeyChars.value());
creationResult->certificateChain = std::move(optCertChain.value());
creationResult->keyBlob = std::move(optKeyBlob.value());
return ScopedAStatus::ok();
}
std::tuple<std::unique_ptr<Item>, keymaster_error_t>
JavacardKeyMintDevice::sendBeginImportWrappedKeyCmd(const std::vector<uint8_t>& transitKey,
const std::vector<uint8_t>& wrappingKeyBlob,
const std::vector<uint8_t>& maskingKey,
const vector<KeyParameter>& unwrappingParams) {
Array request;
request.add(std::vector<uint8_t>(transitKey));
request.add(std::vector<uint8_t>(wrappingKeyBlob));
request.add(std::vector<uint8_t>(maskingKey));
cbor_.addKeyparameters(request, unwrappingParams);
return card_->sendRequest(Instruction::INS_BEGIN_IMPORT_WRAPPED_KEY_CMD, request);
}
std::tuple<std::unique_ptr<Item>, keymaster_error_t>
JavacardKeyMintDevice::sendFinishImportWrappedKeyCmd(
const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
const std::vector<uint8_t>& secureKey, const std::vector<uint8_t>& tag,
const std::vector<uint8_t>& iv, const std::vector<uint8_t>& wrappedKeyDescription,
int64_t passwordSid, int64_t biometricSid) {
Array request;
cbor_.addKeyparameters(request, keyParams);
request.add(static_cast<uint64_t>(keyFormat));
request.add(std::vector<uint8_t>(secureKey));
request.add(std::vector<uint8_t>(tag));
request.add(std::vector<uint8_t>(iv));
request.add(std::vector<uint8_t>(wrappedKeyDescription));
request.add(Uint(passwordSid));
request.add(Uint(biometricSid));
return card_->sendRequest(Instruction::INS_FINISH_IMPORT_WRAPPED_KEY_CMD, request);
}
ScopedAStatus JavacardKeyMintDevice::upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
const vector<KeyParameter>& upgradeParams,
vector<uint8_t>* keyBlob) {
card_->sendPendingEvents();
cppbor::Array request;
// add key blob
request.add(Bstr(keyBlobToUpgrade));
// add key params
cbor_.addKeyparameters(request, upgradeParams);
auto [item, err] = card_->sendRequest(Instruction::INS_UPGRADE_KEY_CMD, request);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending in upgradeKey.";
return km_utils::kmError2ScopedAStatus(err);
}
auto optKeyBlob = cbor_.getByteArrayVec(item, 1);
if (!optKeyBlob) {
LOG(ERROR) << "Error in decoding the response in upgradeKey.";
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
}
*keyBlob = std::move(optKeyBlob.value());
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
Array request;
request.add(Bstr(keyBlob));
auto [item, err] = card_->sendRequest(Instruction::INS_DELETE_KEY_CMD, request);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending in deleteKey.";
return km_utils::kmError2ScopedAStatus(err);
}
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::deleteAllKeys() {
auto [_, err] = card_->sendRequest(Instruction::INS_DELETE_ALL_KEYS_CMD);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending deleteAllKeys.";
card_->setDeleteAllKeysPending();
return km_utils::kmError2ScopedAStatus(err);
}
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::destroyAttestationIds() {
auto [item, err] = card_->sendRequest(Instruction::INS_DESTROY_ATT_IDS_CMD);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending in destroyAttestationIds.";
return km_utils::kmError2ScopedAStatus(err);
}
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::begin(KeyPurpose purpose, const std::vector<uint8_t>& keyBlob,
const std::vector<KeyParameter>& params,
const std::optional<HardwareAuthToken>& authToken,
BeginResult* result) {
card_->sendPendingEvents();
cppbor::Array array;
std::vector<uint8_t> response;
// make request
array.add(Uint(static_cast<uint64_t>(purpose)));
array.add(Bstr(keyBlob));
cbor_.addKeyparameters(array, params);
HardwareAuthToken token = authToken.value_or(HardwareAuthToken());
cbor_.addHardwareAuthToken(array, token);
auto [item, err] = card_->sendRequest(Instruction::INS_BEGIN_OPERATION_CMD, array);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending in begin.";
return km_utils::kmError2ScopedAStatus(err);
}
// return the result
auto keyParams = cbor_.getKeyParameters(item, 1);
auto optOpHandle = cbor_.getUint64(item, 2);
auto optBufMode = cbor_.getUint64(item, 3);
auto optMacLength = cbor_.getUint64(item, 4);
if (!keyParams || !optOpHandle || !optBufMode || !optMacLength) {
LOG(ERROR) << "Error in decoding the response in begin.";
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
}
result->params = std::move(keyParams.value());
result->challenge = optOpHandle.value();
result->operation = ndk::SharedRefBase::make<JavacardKeyMintOperation>(
static_cast<keymaster_operation_handle_t>(optOpHandle.value()),
static_cast<BufferingMode>(optBufMode.value()), optMacLength.value(), card_);
return ScopedAStatus::ok();
}
ScopedAStatus
JavacardKeyMintDevice::deviceLocked(bool passwordOnly,
const std::optional<TimeStampToken>& timestampToken) {
Array request;
int8_t password = 1;
if (!passwordOnly) {
password = 0;
}
request.add(Uint(password));
cbor_.addTimeStampToken(request, timestampToken.value_or(TimeStampToken()));
auto [item, err] = card_->sendRequest(Instruction::INS_DEVICE_LOCKED_CMD, request);
if (err != KM_ERROR_OK) {
return km_utils::kmError2ScopedAStatus(err);
}
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::earlyBootEnded() {
auto [_, err] = card_->sendRequest(Instruction::INS_EARLY_BOOT_ENDED_CMD);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending earlyBootEnded.";
card_->setEarlyBootEndedPending();
return km_utils::kmError2ScopedAStatus(err);
}
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::getKeyCharacteristics(
const std::vector<uint8_t>& keyBlob, const std::vector<uint8_t>& appId,
const std::vector<uint8_t>& appData, std::vector<KeyCharacteristics>* result) {
card_->sendPendingEvents();
cppbor::Array request;
request.add(vector<uint8_t>(keyBlob));
request.add(vector<uint8_t>(appId));
request.add(vector<uint8_t>(appData));
auto [item, err] = card_->sendRequest(Instruction::INS_GET_KEY_CHARACTERISTICS_CMD, request);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending in getKeyCharacteristics.";
return km_utils::kmError2ScopedAStatus(err);
}
auto optKeyChars = cbor_.getKeyCharacteristics(item, 1);
if (!optKeyChars) {
LOG(ERROR) << "Error in sending in upgradeKey.";
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
}
*result = std::move(optKeyChars.value());
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::getRootOfTrustChallenge(std::array<uint8_t, 16>* challenge) {
auto [item, err] = card_->sendRequest(Instruction::INS_GET_ROT_CHALLENGE_CMD);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending in getRootOfTrustChallenge.";
return km_utils::kmError2ScopedAStatus(err);
}
auto optChallenge = cbor_.getByteArrayVec(item, 1);
if (!optChallenge) {
LOG(ERROR) << "Error in sending in upgradeKey.";
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
}
std::move(optChallenge->begin(), optChallenge->begin() + 16, challenge->begin());
return ScopedAStatus::ok();
}
ScopedAStatus JavacardKeyMintDevice::getRootOfTrust(const std::array<uint8_t, 16>& /*challenge*/,
std::vector<uint8_t>* /*rootOfTrust*/) {
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
}
ScopedAStatus JavacardKeyMintDevice::sendRootOfTrust(const std::vector<uint8_t>& rootOfTrust) {
cppbor::Array request;
request.add(EncodedItem(rootOfTrust)); // taggedItem.
auto [item, err] = card_->sendRequest(Instruction::INS_SEND_ROT_DATA_CMD, request);
if (err != KM_ERROR_OK) {
LOG(ERROR) << "Error in sending in sendRootOfTrust.";
return km_utils::kmError2ScopedAStatus(err);
}
LOG(INFO) << "JavacardKeyMintDevice::sendRootOfTrust success";
return ScopedAStatus::ok();
}
keymaster_error_t
JavacardKeyMintDevice::parseWrappedKey(const vector<uint8_t>& wrappedKeyData,
std::vector<uint8_t>& iv, std::vector<uint8_t>& transitKey,
std::vector<uint8_t>& secureKey, std::vector<uint8_t>& tag,
vector<KeyParameter>& authList, KeyFormat& keyFormat,
std::vector<uint8_t>& wrappedKeyDescription) {
KeymasterBlob kmIv;
KeymasterKeyBlob kmTransitKey;
KeymasterKeyBlob kmSecureKey;
KeymasterBlob kmTag;
AuthorizationSet authSet;
keymaster_key_format_t kmKeyFormat;
KeymasterBlob kmWrappedKeyDescription;
size_t keyDataLen = wrappedKeyData.size();
uint8_t* keyData = dup_buffer(wrappedKeyData.data(), keyDataLen);
keymaster_key_blob_t keyMaterial = {keyData, keyDataLen};
keymaster_error_t error =
parse_wrapped_key(KeymasterKeyBlob(keyMaterial), &kmIv, &kmTransitKey, &kmSecureKey, &kmTag,
&authSet, &kmKeyFormat, &kmWrappedKeyDescription);
if (error != KM_ERROR_OK) {
LOG(ERROR) << "Error parsing wrapped key.";
return error;
}
iv = km_utils::kmBlob2vector(kmIv);
transitKey = km_utils::kmBlob2vector(kmTransitKey);
secureKey = km_utils::kmBlob2vector(kmSecureKey);
tag = km_utils::kmBlob2vector(kmTag);
authList = km_utils::kmParamSet2Aidl(authSet);
keyFormat = static_cast<KeyFormat>(kmKeyFormat);
wrappedKeyDescription = km_utils::kmBlob2vector(kmWrappedKeyDescription);
return KM_ERROR_OK;
}
ScopedAStatus JavacardKeyMintDevice::convertStorageKeyToEphemeral(
const std::vector<uint8_t>& /* storageKeyBlob */,
std::vector<uint8_t>* /* ephemeralKeyBlob */) {
return km_utils::kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
}
binder_status_t JavacardKeyMintDevice::dump(int /* fd */, const char** /* p */, uint32_t /* q */) {
LOG(INFO) << "\n KeyMint-JavacardKeyMintDevice HAL MemoryLeak Info = \n"
<< ::android::GetUnreachableMemoryString(true, 10000).c_str();
return STATUS_OK;
}
} // namespace aidl::android::hardware::security::keymint