| /* |
| ** |
| ** 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 <cutils/log.h> |
| |
| using std::shared_ptr; |
| 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 |