You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
14 KiB
304 lines
14 KiB
/*
|
|
**
|
|
** Copyright 2017, 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.
|
|
*/
|
|
#include "keymaster_passthrough_operation.h"
|
|
#include <keymaster/legacy_support/keymaster_passthrough_engine.h>
|
|
#include <keymaster/legacy_support/keymaster_passthrough_key.h>
|
|
|
|
#include <hardware/keymaster1.h>
|
|
#include <hardware/keymaster2.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
#include <type_traits>
|
|
|
|
#define LOG_TAG "Keymaster2Engine"
|
|
#include <android/log.h>
|
|
|
|
using std::unique_ptr;
|
|
|
|
namespace keymaster {
|
|
|
|
template <typename KeymasterDeviceType>
|
|
class TKeymasterPassthroughEngine : public KeymasterPassthroughEngine {
|
|
using opfactory_t = KeymasterPassthroughOperationFactory<KeymasterDeviceType>;
|
|
|
|
public:
|
|
/**
|
|
* The engine takes ownership of the device, and will close it during destruction.
|
|
*/
|
|
explicit TKeymasterPassthroughEngine(const KeymasterDeviceType* km_device)
|
|
: km_device_(km_device) {
|
|
rsa_encrypt_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_RSA, KM_PURPOSE_ENCRYPT, km_device_));
|
|
rsa_decrypt_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_RSA, KM_PURPOSE_DECRYPT, km_device_));
|
|
rsa_sign_op_factory_.reset(new opfactory_t(KM_ALGORITHM_RSA, KM_PURPOSE_SIGN, km_device_));
|
|
rsa_verify_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_RSA, KM_PURPOSE_VERIFY, km_device_));
|
|
ec_encrypt_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_ENCRYPT, km_device_));
|
|
ec_decrypt_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_DECRYPT, km_device_));
|
|
ec_sign_op_factory_.reset(new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_SIGN, km_device_));
|
|
ec_verify_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_VERIFY, km_device_));
|
|
ec_derive_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_EC, KM_PURPOSE_DERIVE_KEY, km_device_));
|
|
aes_encrypt_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_AES, KM_PURPOSE_ENCRYPT, km_device_));
|
|
aes_decrypt_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_AES, KM_PURPOSE_DECRYPT, km_device_));
|
|
triple_des_encrypt_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_TRIPLE_DES, KM_PURPOSE_ENCRYPT, km_device_));
|
|
triple_des_decrypt_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_TRIPLE_DES, KM_PURPOSE_DECRYPT, km_device_));
|
|
hmac_sign_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_HMAC, KM_PURPOSE_SIGN, km_device_));
|
|
hmac_verify_op_factory_.reset(
|
|
new opfactory_t(KM_ALGORITHM_HMAC, KM_PURPOSE_VERIFY, km_device_));
|
|
}
|
|
virtual ~TKeymasterPassthroughEngine() {
|
|
// QUIRK: we only take ownership if this is a KM2 device.
|
|
// For KM1 the Keymaster1Engine takes ownership
|
|
if (std::is_same<KeymasterDeviceType, keymaster2_device_t>::value)
|
|
km_device_->common.close(
|
|
reinterpret_cast<hw_device_t*>(const_cast<KeymasterDeviceType*>(km_device_)));
|
|
}
|
|
|
|
keymaster_error_t GenerateKey(const AuthorizationSet& key_description,
|
|
KeymasterKeyBlob* key_material, AuthorizationSet* hw_enforced,
|
|
AuthorizationSet* sw_enforced) const override;
|
|
|
|
keymaster_error_t ImportKey(const AuthorizationSet& key_description,
|
|
keymaster_key_format_t input_key_material_format,
|
|
const KeymasterKeyBlob& input_key_material,
|
|
KeymasterKeyBlob* output_key_blob, AuthorizationSet* hw_enforced,
|
|
AuthorizationSet* sw_enforced) const override;
|
|
keymaster_error_t ExportKey(keymaster_key_format_t format, const KeymasterKeyBlob& blob,
|
|
const KeymasterBlob& client_id, const KeymasterBlob& app_data,
|
|
KeymasterBlob* export_data) const override {
|
|
keymaster_blob_t my_export_data = {};
|
|
keymaster_error_t error = km_device_->export_key(km_device_, format, &blob, &client_id,
|
|
&app_data, &my_export_data);
|
|
if (error != KM_ERROR_OK) return error;
|
|
*export_data = KeymasterBlob(my_export_data.data, my_export_data.data_length);
|
|
free(const_cast<uint8_t*>(my_export_data.data));
|
|
if (export_data->data == nullptr) {
|
|
return KM_ERROR_MEMORY_ALLOCATION_FAILED;
|
|
}
|
|
return error;
|
|
}
|
|
keymaster_error_t DeleteKey(const KeymasterKeyBlob& blob) const override {
|
|
return km_device_->delete_key(km_device_, &blob);
|
|
}
|
|
keymaster_error_t DeleteAllKeys() const override {
|
|
return km_device_->delete_all_keys(km_device_);
|
|
}
|
|
OperationFactory* GetOperationFactory(keymaster_purpose_t purpose,
|
|
keymaster_algorithm_t algorithm) const override {
|
|
switch (algorithm) {
|
|
case KM_ALGORITHM_RSA:
|
|
switch (purpose) {
|
|
case KM_PURPOSE_ENCRYPT:
|
|
return rsa_encrypt_op_factory_.get();
|
|
case KM_PURPOSE_DECRYPT:
|
|
return rsa_decrypt_op_factory_.get();
|
|
case KM_PURPOSE_SIGN:
|
|
return rsa_sign_op_factory_.get();
|
|
case KM_PURPOSE_VERIFY:
|
|
return rsa_verify_op_factory_.get();
|
|
default:
|
|
return nullptr;
|
|
}
|
|
case KM_ALGORITHM_EC:
|
|
switch (purpose) {
|
|
case KM_PURPOSE_ENCRYPT:
|
|
return ec_encrypt_op_factory_.get();
|
|
case KM_PURPOSE_DECRYPT:
|
|
return ec_decrypt_op_factory_.get();
|
|
case KM_PURPOSE_SIGN:
|
|
return ec_sign_op_factory_.get();
|
|
case KM_PURPOSE_VERIFY:
|
|
return ec_verify_op_factory_.get();
|
|
case KM_PURPOSE_DERIVE_KEY:
|
|
return ec_derive_op_factory_.get();
|
|
default:
|
|
return nullptr;
|
|
}
|
|
case KM_ALGORITHM_AES:
|
|
switch (purpose) {
|
|
case KM_PURPOSE_ENCRYPT:
|
|
return aes_encrypt_op_factory_.get();
|
|
case KM_PURPOSE_DECRYPT:
|
|
return aes_decrypt_op_factory_.get();
|
|
default:
|
|
return nullptr;
|
|
}
|
|
case KM_ALGORITHM_TRIPLE_DES:
|
|
switch (purpose) {
|
|
case KM_PURPOSE_ENCRYPT:
|
|
return triple_des_encrypt_op_factory_.get();
|
|
case KM_PURPOSE_DECRYPT:
|
|
return triple_des_decrypt_op_factory_.get();
|
|
default:
|
|
return nullptr;
|
|
}
|
|
case KM_ALGORITHM_HMAC:
|
|
switch (purpose) {
|
|
case KM_PURPOSE_SIGN:
|
|
return hmac_sign_op_factory_.get();
|
|
case KM_PURPOSE_VERIFY:
|
|
return hmac_verify_op_factory_.get();
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
const KeymasterDeviceType* device() const { return km_device_; }
|
|
|
|
private:
|
|
TKeymasterPassthroughEngine(const KeymasterPassthroughEngine&) = delete; // Uncopyable
|
|
void operator=(const KeymasterPassthroughEngine&) = delete; // Unassignable
|
|
|
|
const KeymasterDeviceType* const km_device_;
|
|
std::unique_ptr<opfactory_t> rsa_encrypt_op_factory_;
|
|
std::unique_ptr<opfactory_t> rsa_decrypt_op_factory_;
|
|
std::unique_ptr<opfactory_t> rsa_sign_op_factory_;
|
|
std::unique_ptr<opfactory_t> rsa_verify_op_factory_;
|
|
std::unique_ptr<opfactory_t> ec_encrypt_op_factory_;
|
|
std::unique_ptr<opfactory_t> ec_decrypt_op_factory_;
|
|
std::unique_ptr<opfactory_t> ec_sign_op_factory_;
|
|
std::unique_ptr<opfactory_t> ec_verify_op_factory_;
|
|
std::unique_ptr<opfactory_t> ec_derive_op_factory_;
|
|
std::unique_ptr<opfactory_t> aes_encrypt_op_factory_;
|
|
std::unique_ptr<opfactory_t> aes_decrypt_op_factory_;
|
|
std::unique_ptr<opfactory_t> triple_des_encrypt_op_factory_;
|
|
std::unique_ptr<opfactory_t> triple_des_decrypt_op_factory_;
|
|
std::unique_ptr<opfactory_t> hmac_sign_op_factory_;
|
|
std::unique_ptr<opfactory_t> hmac_verify_op_factory_;
|
|
};
|
|
|
|
static void ConvertCharacteristics(const keymaster_key_characteristics_t& characteristics,
|
|
AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) {
|
|
if (hw_enforced) hw_enforced->Reinitialize(characteristics.hw_enforced);
|
|
if (sw_enforced) sw_enforced->Reinitialize(characteristics.sw_enforced);
|
|
}
|
|
|
|
template <>
|
|
keymaster_error_t TKeymasterPassthroughEngine<keymaster1_device_t>::GenerateKey(
|
|
const AuthorizationSet& key_description, KeymasterKeyBlob* key_blob,
|
|
AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
|
|
assert(key_blob);
|
|
|
|
keymaster_key_characteristics_t* characteristics = nullptr;
|
|
keymaster_key_blob_t blob = {};
|
|
keymaster_error_t error =
|
|
km_device_->generate_key(km_device_, &key_description, &blob, &characteristics);
|
|
if (error != KM_ERROR_OK) return error;
|
|
unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
|
|
key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
|
|
key_blob->key_material_size = blob.key_material_size;
|
|
|
|
ConvertCharacteristics(*characteristics, hw_enforced, sw_enforced);
|
|
keymaster_free_characteristics(characteristics);
|
|
free(characteristics);
|
|
return error;
|
|
}
|
|
template <>
|
|
keymaster_error_t TKeymasterPassthroughEngine<keymaster2_device_t>::GenerateKey(
|
|
const AuthorizationSet& key_description, KeymasterKeyBlob* key_blob,
|
|
AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
|
|
assert(key_blob);
|
|
|
|
keymaster_key_characteristics_t characteristics = {};
|
|
keymaster_key_blob_t blob = {};
|
|
keymaster_error_t error =
|
|
km_device_->generate_key(km_device_, &key_description, &blob, &characteristics);
|
|
if (error != KM_ERROR_OK) return error;
|
|
unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
|
|
key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
|
|
key_blob->key_material_size = blob.key_material_size;
|
|
|
|
ConvertCharacteristics(characteristics, hw_enforced, sw_enforced);
|
|
keymaster_free_characteristics(&characteristics);
|
|
return error;
|
|
}
|
|
|
|
template <>
|
|
keymaster_error_t TKeymasterPassthroughEngine<keymaster1_device_t>::ImportKey(
|
|
const AuthorizationSet& key_description, keymaster_key_format_t input_key_material_format,
|
|
const KeymasterKeyBlob& input_key_material, KeymasterKeyBlob* output_key_blob,
|
|
AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
|
|
assert(output_key_blob);
|
|
|
|
keymaster_key_characteristics_t* characteristics = {};
|
|
const keymaster_blob_t input_key = {input_key_material.key_material,
|
|
input_key_material.key_material_size};
|
|
keymaster_key_blob_t blob = {};
|
|
keymaster_error_t error =
|
|
km_device_->import_key(km_device_, &key_description, input_key_material_format, &input_key,
|
|
&blob, &characteristics);
|
|
if (error != KM_ERROR_OK) return error;
|
|
unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
|
|
|
|
*output_key_blob = KeymasterKeyBlob(blob);
|
|
|
|
ConvertCharacteristics(*characteristics, hw_enforced, sw_enforced);
|
|
keymaster_free_characteristics(characteristics);
|
|
free(characteristics);
|
|
return error;
|
|
}
|
|
|
|
template <>
|
|
keymaster_error_t TKeymasterPassthroughEngine<keymaster2_device_t>::ImportKey(
|
|
const AuthorizationSet& key_description, keymaster_key_format_t input_key_material_format,
|
|
const KeymasterKeyBlob& input_key_material, KeymasterKeyBlob* output_key_blob,
|
|
AuthorizationSet* hw_enforced, AuthorizationSet* sw_enforced) const {
|
|
assert(output_key_blob);
|
|
|
|
keymaster_key_characteristics_t characteristics = {};
|
|
const keymaster_blob_t input_key = {input_key_material.key_material,
|
|
input_key_material.key_material_size};
|
|
keymaster_key_blob_t blob = {};
|
|
keymaster_error_t error =
|
|
km_device_->import_key(km_device_, &key_description, input_key_material_format, &input_key,
|
|
&blob, &characteristics);
|
|
if (error != KM_ERROR_OK) return error;
|
|
unique_ptr<uint8_t, Malloc_Delete> blob_deleter(const_cast<uint8_t*>(blob.key_material));
|
|
// TODO why duplicate the blob if we have ownership here anyway?
|
|
output_key_blob->key_material = dup_buffer(blob.key_material, blob.key_material_size);
|
|
output_key_blob->key_material_size = blob.key_material_size;
|
|
|
|
ConvertCharacteristics(characteristics, hw_enforced, sw_enforced);
|
|
keymaster_free_characteristics(&characteristics);
|
|
return error;
|
|
}
|
|
|
|
typedef UniquePtr<KeymasterPassthroughEngine> engine_ptr_t;
|
|
|
|
engine_ptr_t KeymasterPassthroughEngine::createInstance(const keymaster1_device_t* dev) {
|
|
return engine_ptr_t(new TKeymasterPassthroughEngine<keymaster1_device_t>(dev));
|
|
}
|
|
engine_ptr_t KeymasterPassthroughEngine::createInstance(const keymaster2_device_t* dev) {
|
|
return engine_ptr_t(new TKeymasterPassthroughEngine<keymaster2_device_t>(dev));
|
|
}
|
|
|
|
} // namespace keymaster
|