Files
hardware_interfaces/keymaster/3.0/default/KeymasterDevice.cpp
Bartosz Fabianowski 2377553df2 Add manufacturer and model to device ID attestation
Discussions have shown that in addition to brand, device and product,
we should also allow devices to attest their manufacturer and model.

Bug: 36433192
Test: GTS com.google.android.gts.security.DeviceIdAttestationHostTest

Change-Id: I5a9fd839497976cdb1e44cbe4a2d5b7730732b4c
2017-03-20 14:01:03 +01:00

720 lines
26 KiB
C++

/*
**
** Copyright 2016, 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.
*/
#define LOG_TAG "android.hardware.keymaster@3.0-impl"
#include "KeymasterDevice.h"
#include <cutils/log.h>
#include <hardware/keymaster_defs.h>
#include <keymaster/keymaster_configuration.h>
#include <keymaster/soft_keymaster_device.h>
namespace android {
namespace hardware {
namespace keymaster {
namespace V3_0 {
namespace implementation {
using ::keymaster::SoftKeymasterDevice;
class SoftwareOnlyHidlKeymasterEnforcement : public ::keymaster::KeymasterEnforcement {
public:
SoftwareOnlyHidlKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
uint32_t get_current_time() const override {
struct timespec tp;
int err = clock_gettime(CLOCK_MONOTONIC, &tp);
if (err || tp.tv_sec < 0) return 0;
return static_cast<uint32_t>(tp.tv_sec);
}
bool activation_date_valid(uint64_t) const override { return true; }
bool expiration_date_passed(uint64_t) const override { return false; }
bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const override { return false; }
bool ValidateTokenSignature(const hw_auth_token_t&) const override { return true; }
};
class SoftwareOnlyHidlKeymasterContext : public ::keymaster::SoftKeymasterContext {
public:
SoftwareOnlyHidlKeymasterContext() : enforcement_(new SoftwareOnlyHidlKeymasterEnforcement) {}
::keymaster::KeymasterEnforcement* enforcement_policy() override { return enforcement_.get(); }
private:
std::unique_ptr<::keymaster::KeymasterEnforcement> enforcement_;
};
static int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
keymaster0_device_t* km0_device = NULL;
keymaster_error_t error = KM_ERROR_OK;
int rc = keymaster0_open(mod, &km0_device);
if (rc) {
ALOGE("Error opening keystore keymaster0 device.");
goto err;
}
if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
ALOGI("Keymaster0 module is software-only. Using SoftKeymasterDevice instead.");
km0_device->common.close(&km0_device->common);
km0_device = NULL;
// SoftKeymasterDevice will be deleted by keymaster_device_release()
*dev = soft_keymaster.release()->keymaster2_device();
return 0;
}
ALOGD("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
error = soft_keymaster->SetHardwareDevice(km0_device);
km0_device = NULL; // SoftKeymasterDevice has taken ownership.
if (error != KM_ERROR_OK) {
ALOGE("Got error %d from SetHardwareDevice", error);
rc = error;
goto err;
}
// SoftKeymasterDevice will be deleted by keymaster_device_release()
*dev = soft_keymaster.release()->keymaster2_device();
return 0;
err:
if (km0_device) km0_device->common.close(&km0_device->common);
*dev = NULL;
return rc;
}
static int keymaster1_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
keymaster1_device_t* km1_device = nullptr;
keymaster_error_t error = KM_ERROR_OK;
int rc = keymaster1_open(mod, &km1_device);
if (rc) {
ALOGE("Error %d opening keystore keymaster1 device", rc);
goto err;
}
ALOGD("Wrapping keymaster1 module %s with SofKeymasterDevice", mod->name);
error = soft_keymaster->SetHardwareDevice(km1_device);
km1_device = nullptr; // SoftKeymasterDevice has taken ownership.
if (error != KM_ERROR_OK) {
ALOGE("Got error %d from SetHardwareDevice", error);
rc = error;
goto err;
}
// SoftKeymasterDevice will be deleted by keymaster_device_release()
*dev = soft_keymaster.release()->keymaster2_device();
return 0;
err:
if (km1_device) km1_device->common.close(&km1_device->common);
*dev = NULL;
return rc;
}
static int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
ALOGI("Found keymaster2 module %s, version %x", mod->name, mod->module_api_version);
keymaster2_device_t* km2_device = nullptr;
int rc = keymaster2_open(mod, &km2_device);
if (rc) {
ALOGE("Error %d opening keystore keymaster2 device", rc);
goto err;
}
*dev = km2_device;
return 0;
err:
if (km2_device) km2_device->common.close(&km2_device->common);
*dev = nullptr;
return rc;
}
static int keymaster_device_initialize(keymaster2_device_t** dev, uint32_t* version,
bool* supports_ec) {
const hw_module_t* mod;
*supports_ec = true;
int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
if (rc) {
ALOGI("Could not find any keystore module, using software-only implementation.");
// SoftKeymasterDevice will be deleted by keymaster_device_release()
*dev = (new SoftKeymasterDevice(new SoftwareOnlyHidlKeymasterContext))->keymaster2_device();
*version = -1;
return 0;
}
if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
*version = 0;
int rc = keymaster0_device_initialize(mod, dev);
if (rc == 0 && ((*dev)->flags & KEYMASTER_SUPPORTS_EC) == 0) {
*supports_ec = false;
}
return rc;
} else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
*version = 1;
return keymaster1_device_initialize(mod, dev);
} else {
*version = 2;
return keymaster2_device_initialize(mod, dev);
}
}
KeymasterDevice::~KeymasterDevice() {
if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common);
}
static inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
return keymaster_tag_get_type(tag);
}
/**
* legacy_enum_conversion converts enums from hidl to keymaster and back. Currently, this is just a
* cast to make the compiler happy. One of two thigs should happen though:
* TODO The keymaster enums should become aliases for the hidl generated enums so that we have a
* single point of truth. Then this cast function can go away.
*/
inline static keymaster_tag_t legacy_enum_conversion(const Tag value) {
return keymaster_tag_t(value);
}
inline static Tag legacy_enum_conversion(const keymaster_tag_t value) {
return Tag(value);
}
inline static keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
return keymaster_purpose_t(value);
}
inline static keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
return keymaster_key_format_t(value);
}
inline static ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
return ErrorCode(value);
}
class KmParamSet : public keymaster_key_param_set_t {
public:
KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
params = new keymaster_key_param_t[keyParams.size()];
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:
params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
break;
case KM_UINT:
case KM_UINT_REP:
params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
break;
case KM_ULONG:
case KM_ULONG_REP:
params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
break;
case KM_DATE:
params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
break;
case KM_BOOL:
if (keyParams[i].f.boolValue)
params[i] = keymaster_param_bool(tag);
else
params[i].tag = KM_TAG_INVALID;
break;
case KM_BIGNUM:
case KM_BYTES:
params[i] =
keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
break;
case KM_INVALID:
default:
params[i].tag = KM_TAG_INVALID;
/* just skip */
break;
}
}
}
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; }
};
inline static KmParamSet hidlParams2KmParamSet(const hidl_vec<KeyParameter>& params) {
return KmParamSet(params);
}
inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec<uint8_t>& blob) {
/* hidl unmarshals funny pointers if the the blob is empty */
if (blob.size()) return {&blob[0], blob.size()};
return {nullptr, 0};
}
inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec<uint8_t>& blob) {
/* hidl unmarshals funny pointers if the the blob is empty */
if (blob.size()) return {&blob[0], blob.size()};
return {nullptr, 0};
}
inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
hidl_vec<uint8_t> result;
result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
return result;
}
inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
hidl_vec<uint8_t> result;
result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
return result;
}
inline static hidl_vec<hidl_vec<uint8_t>>
kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) {
hidl_vec<hidl_vec<uint8_t>> result;
if (!cert_chain || cert_chain->entry_count == 0 || !cert_chain->entries) return result;
result.resize(cert_chain->entry_count);
for (size_t i = 0; i < cert_chain->entry_count; ++i) {
auto& entry = cert_chain->entries[i];
result[i] = kmBlob2hidlVec(entry);
}
return result;
}
static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
hidl_vec<KeyParameter> 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<unsigned char*>(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;
}
// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
Return<void> KeymasterDevice::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
bool is_secure = false;
bool supports_symmetric_cryptography = false;
bool supports_attestation = false;
switch (hardware_version_) {
case 2:
supports_attestation = true;
/* Falls through */
case 1:
supports_symmetric_cryptography = true;
/* Falls through */
case 0:
is_secure = true;
break;
};
_hidl_cb(is_secure, hardware_supports_ec_, supports_symmetric_cryptography,
supports_attestation);
return Void();
}
Return<ErrorCode> KeymasterDevice::addRngEntropy(const hidl_vec<uint8_t>& data) {
if (!data.size()) return ErrorCode::OK;
return legacy_enum_conversion(
keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));
}
Return<void> KeymasterDevice::generateKey(const hidl_vec<KeyParameter>& keyParams,
generateKey_cb _hidl_cb) {
// result variables for the wire
KeyCharacteristics resultCharacteristics;
hidl_vec<uint8_t> resultKeyBlob;
// result variables the backend understands
keymaster_key_blob_t key_blob{nullptr, 0};
keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
// convert the parameter set to something our backend understands
auto kmParams = hidlParams2KmParamSet(keyParams);
auto rc = keymaster_device_->generate_key(keymaster_device_, &kmParams, &key_blob,
&key_characteristics);
if (rc == KM_ERROR_OK) {
// on success convert the result to wire format
resultKeyBlob = kmBlob2hidlVec(key_blob);
resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
}
// send results off to the client
_hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
// free buffers that we are responsible for
if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
keymaster_free_characteristics(&key_characteristics);
return Void();
}
Return<void> KeymasterDevice::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
const hidl_vec<uint8_t>& clientId,
const hidl_vec<uint8_t>& appData,
getKeyCharacteristics_cb _hidl_cb) {
// result variables for the wire
KeyCharacteristics resultCharacteristics;
// result variables the backend understands
keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
auto kmClientId = hidlVec2KmBlob(clientId);
auto kmAppData = hidlVec2KmBlob(appData);
auto rc = keymaster_device_->get_key_characteristics(
keymaster_device_, keyBlob.size() ? &kmKeyBlob : nullptr,
clientId.size() ? &kmClientId : nullptr, appData.size() ? &kmAppData : nullptr,
&key_characteristics);
if (rc == KM_ERROR_OK) {
resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
}
_hidl_cb(legacy_enum_conversion(rc), resultCharacteristics);
keymaster_free_characteristics(&key_characteristics);
return Void();
}
Return<void> KeymasterDevice::importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) {
// result variables for the wire
KeyCharacteristics resultCharacteristics;
hidl_vec<uint8_t> resultKeyBlob;
// result variables the backend understands
keymaster_key_blob_t key_blob{nullptr, 0};
keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
auto kmParams = hidlParams2KmParamSet(params);
auto kmKeyData = hidlVec2KmBlob(keyData);
auto rc = keymaster_device_->import_key(keymaster_device_, &kmParams,
legacy_enum_conversion(keyFormat), &kmKeyData,
&key_blob, &key_characteristics);
if (rc == KM_ERROR_OK) {
// on success convert the result to wire format
// (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
resultKeyBlob = kmBlob2hidlVec(key_blob);
resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
}
_hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
// free buffers that we are responsible for
if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
keymaster_free_characteristics(&key_characteristics);
return Void();
}
Return<void> KeymasterDevice::exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
const hidl_vec<uint8_t>& clientId,
const hidl_vec<uint8_t>& appData, exportKey_cb _hidl_cb) {
// result variables for the wire
hidl_vec<uint8_t> resultKeyBlob;
// result variables the backend understands
keymaster_blob_t out_blob{nullptr, 0};
auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
auto kmClientId = hidlVec2KmBlob(clientId);
auto kmAppData = hidlVec2KmBlob(appData);
auto rc = keymaster_device_->export_key(keymaster_device_, legacy_enum_conversion(exportFormat),
keyBlob.size() ? &kmKeyBlob : nullptr,
clientId.size() ? &kmClientId : nullptr,
appData.size() ? &kmAppData : nullptr, &out_blob);
if (rc == KM_ERROR_OK) {
// on success convert the result to wire format
// (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
resultKeyBlob = kmBlob2hidlVec(out_blob);
}
_hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
// free buffers that we are responsible for
if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
return Void();
}
Return<void> KeymasterDevice::attestKey(const hidl_vec<uint8_t>& keyToAttest,
const hidl_vec<KeyParameter>& attestParams,
attestKey_cb _hidl_cb) {
hidl_vec<hidl_vec<uint8_t>> resultCertChain;
for (size_t i = 0; i < attestParams.size(); ++i) {
switch (attestParams[i].tag) {
case Tag::ATTESTATION_ID_BRAND:
case Tag::ATTESTATION_ID_DEVICE:
case Tag::ATTESTATION_ID_PRODUCT:
case Tag::ATTESTATION_ID_SERIAL:
case Tag::ATTESTATION_ID_IMEI:
case Tag::ATTESTATION_ID_MEID:
case Tag::ATTESTATION_ID_MANUFACTURER:
case Tag::ATTESTATION_ID_MODEL:
// Device id attestation may only be supported if the device is able to permanently
// destroy its knowledge of the ids. This device is unable to do this, so it must
// never perform any device id attestation.
_hidl_cb(ErrorCode::CANNOT_ATTEST_IDS, resultCertChain);
return Void();
default:
break;
}
}
keymaster_cert_chain_t cert_chain{nullptr, 0};
auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest);
auto kmAttestParams = hidlParams2KmParamSet(attestParams);
auto rc = keymaster_device_->attest_key(keymaster_device_, &kmKeyToAttest, &kmAttestParams,
&cert_chain);
if (rc == KM_ERROR_OK) {
resultCertChain = kmCertChain2Hidl(&cert_chain);
}
_hidl_cb(legacy_enum_conversion(rc), resultCertChain);
keymaster_free_cert_chain(&cert_chain);
return Void();
}
Return<void> KeymasterDevice::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
const hidl_vec<KeyParameter>& upgradeParams,
upgradeKey_cb _hidl_cb) {
// result variables for the wire
hidl_vec<uint8_t> resultKeyBlob;
// result variables the backend understands
keymaster_key_blob_t key_blob{nullptr, 0};
auto kmKeyBlobToUpgrade = hidlVec2KmKeyBlob(keyBlobToUpgrade);
auto kmUpgradeParams = hidlParams2KmParamSet(upgradeParams);
auto rc = keymaster_device_->upgrade_key(keymaster_device_, &kmKeyBlobToUpgrade,
&kmUpgradeParams, &key_blob);
if (rc == KM_ERROR_OK) {
// on success convert the result to wire format
resultKeyBlob = kmBlob2hidlVec(key_blob);
}
_hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
return Void();
}
Return<ErrorCode> KeymasterDevice::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
}
Return<ErrorCode> KeymasterDevice::deleteAllKeys() {
if (keymaster_device_->delete_all_keys == nullptr) {
return ErrorCode::UNIMPLEMENTED;
}
return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
}
Return<ErrorCode> KeymasterDevice::destroyAttestationIds() {
return ErrorCode::UNIMPLEMENTED;
}
Return<void> KeymasterDevice::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) {
// result variables for the wire
hidl_vec<KeyParameter> resultParams;
uint64_t resultOpHandle = 0;
// result variables the backend understands
keymaster_key_param_set_t out_params{nullptr, 0};
keymaster_operation_handle_t& operation_handle = resultOpHandle;
auto kmKey = hidlVec2KmKeyBlob(key);
auto kmInParams = hidlParams2KmParamSet(inParams);
auto rc = keymaster_device_->begin(keymaster_device_, legacy_enum_conversion(purpose), &kmKey,
&kmInParams, &out_params, &operation_handle);
if (rc == KM_ERROR_OK) resultParams = kmParamSet2Hidl(out_params);
_hidl_cb(legacy_enum_conversion(rc), resultParams, resultOpHandle);
keymaster_free_param_set(&out_params);
return Void();
}
Return<void> KeymasterDevice::update(uint64_t operationHandle,
const hidl_vec<KeyParameter>& inParams,
const hidl_vec<uint8_t>& input, update_cb _hidl_cb) {
// result variables for the wire
uint32_t resultConsumed = 0;
hidl_vec<KeyParameter> resultParams;
hidl_vec<uint8_t> resultBlob;
// result variables the backend understands
size_t consumed = 0;
keymaster_key_param_set_t out_params{nullptr, 0};
keymaster_blob_t out_blob{nullptr, 0};
auto kmInParams = hidlParams2KmParamSet(inParams);
auto kmInput = hidlVec2KmBlob(input);
auto rc = keymaster_device_->update(keymaster_device_, operationHandle, &kmInParams, &kmInput,
&consumed, &out_params, &out_blob);
if (rc == KM_ERROR_OK) {
resultConsumed = consumed;
resultParams = kmParamSet2Hidl(out_params);
resultBlob = kmBlob2hidlVec(out_blob);
}
_hidl_cb(legacy_enum_conversion(rc), resultConsumed, resultParams, resultBlob);
keymaster_free_param_set(&out_params);
if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
return Void();
}
Return<void> KeymasterDevice::finish(uint64_t operationHandle,
const hidl_vec<KeyParameter>& inParams,
const hidl_vec<uint8_t>& input,
const hidl_vec<uint8_t>& signature, finish_cb _hidl_cb) {
// result variables for the wire
hidl_vec<KeyParameter> resultParams;
hidl_vec<uint8_t> resultBlob;
// result variables the backend understands
keymaster_key_param_set_t out_params{nullptr, 0};
keymaster_blob_t out_blob{nullptr, 0};
auto kmInParams = hidlParams2KmParamSet(inParams);
auto kmInput = hidlVec2KmBlob(input);
auto kmSignature = hidlVec2KmBlob(signature);
auto rc = keymaster_device_->finish(keymaster_device_, operationHandle, &kmInParams, &kmInput,
&kmSignature, &out_params, &out_blob);
if (rc == KM_ERROR_OK) {
resultParams = kmParamSet2Hidl(out_params);
resultBlob = kmBlob2hidlVec(out_blob);
}
_hidl_cb(legacy_enum_conversion(rc), resultParams, resultBlob);
keymaster_free_param_set(&out_params);
if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
return Void();
}
Return<ErrorCode> KeymasterDevice::abort(uint64_t operationHandle) {
return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
}
IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* /* name */) {
keymaster2_device_t* dev = nullptr;
uint32_t version;
bool supports_ec;
auto rc = keymaster_device_initialize(&dev, &version, &supports_ec);
if (rc) return nullptr;
auto kmrc = ::keymaster::ConfigureDevice(dev);
if (kmrc != KM_ERROR_OK) {
dev->common.close(&dev->common);
return nullptr;
}
return new KeymasterDevice(dev, version, supports_ec);
}
} // namespace implementation
} // namespace V3_0
} // namespace keymaster
} // namespace hardware
} // namespace android