mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
This is needed to support the keystore statistics gathering initiative. It will allow us to get information about what kinds of keymaster implementations exist in the ecosystem, and which ones fail in which ways. Bug: 36549319 Test: Will add to VTS tests Change-Id: I49ee4623656060d69a6de7723b11cd715150451a
724 lines
26 KiB
C++
724 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,
|
|
bool* supports_all_digests) {
|
|
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()
|
|
*supports_all_digests = soft_keymaster->supports_all_digests();
|
|
*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, bool* supports_all_digests) {
|
|
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;
|
|
*supports_all_digests = false;
|
|
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, supports_all_digests);
|
|
} else {
|
|
*version = 2;
|
|
*supports_all_digests = true;
|
|
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 = !(keymaster_device_->flags & KEYMASTER_SOFTWARE_ONLY);
|
|
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;
|
|
break;
|
|
};
|
|
|
|
_hidl_cb(is_secure, hardware_supports_ec_, supports_symmetric_cryptography,
|
|
supports_attestation, hardware_supports_all_digests_,
|
|
keymaster_device_->common.module->name, keymaster_device_->common.module->author);
|
|
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:
|
|
// 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) {
|
|
if (keymaster_device_->delete_key == nullptr) {
|
|
return ErrorCode::UNIMPLEMENTED;
|
|
}
|
|
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;
|
|
bool supports_all_digests;
|
|
auto rc = keymaster_device_initialize(&dev, &version, &supports_ec, &supports_all_digests);
|
|
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, supports_all_digests);
|
|
}
|
|
|
|
} // namespace implementation
|
|
} // namespace V3_0
|
|
} // namespace keymaster
|
|
} // namespace hardware
|
|
} // namespace android
|