/* * Copyright 2015 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 #include #include #include #include #include #include #include #include #include #include #define LOG_TAG "SoftKeymasterDevice" #include #include #include #include #include #include #include "openssl_utils.h" struct keystore_module soft_keymaster1_device_module = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = KEYMASTER_MODULE_API_VERSION_1_0, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = KEYSTORE_HARDWARE_MODULE_ID, .name = "OpenSSL-based SoftKeymaster HAL", .author = "The Android Open Source Project", .methods = nullptr, .dso = 0, .reserved = {}, }, }; struct keystore_module soft_keymaster2_device_module = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = KEYMASTER_MODULE_API_VERSION_2_0, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = KEYSTORE_HARDWARE_MODULE_ID, .name = "OpenSSL-based SoftKeymaster HAL", .author = "The Android Open Source Project", .methods = nullptr, .dso = 0, .reserved = {}, }, }; namespace keymaster { const size_t kMaximumAttestationChallengeLength = 128; const size_t kOperationTableSize = 16; template std::vector make_vector(const T* array, size_t len) { return std::vector(array, array + len); } static keymaster_error_t add_digests(keymaster1_device_t* dev, keymaster_algorithm_t algorithm, keymaster_purpose_t purpose, SoftKeymasterDevice::DigestMap* map) { auto key = std::make_pair(algorithm, purpose); keymaster_digest_t* digests; size_t digests_length; keymaster_error_t error = dev->get_supported_digests(dev, algorithm, purpose, &digests, &digests_length); if (error != KM_ERROR_OK) { LOG_E("Error %d getting supported digests from keymaster1 device", error); return error; } std::unique_ptr digests_deleter(digests); (*map)[key] = make_vector(digests, digests_length); return KM_ERROR_OK; } static keymaster_error_t map_digests(keymaster1_device_t* dev, SoftKeymasterDevice::DigestMap* map) { map->clear(); keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC}; keymaster_purpose_t sig_purposes[] = {KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY}; for (auto algorithm : sig_algorithms) for (auto purpose : sig_purposes) { keymaster_error_t error = add_digests(dev, algorithm, purpose, map); if (error != KM_ERROR_OK) return error; } keymaster_algorithm_t crypt_algorithms[] = {KM_ALGORITHM_RSA}; keymaster_purpose_t crypt_purposes[] = {KM_PURPOSE_ENCRYPT, KM_PURPOSE_DECRYPT}; for (auto algorithm : crypt_algorithms) for (auto purpose : crypt_purposes) { keymaster_error_t error = add_digests(dev, algorithm, purpose, map); if (error != KM_ERROR_OK) return error; } return KM_ERROR_OK; } SoftKeymasterDevice::SoftKeymasterDevice() : wrapped_km0_device_(nullptr), wrapped_km1_device_(nullptr), context_(new SoftKeymasterContext), impl_(new AndroidKeymaster(context_, kOperationTableSize)), configured_(false) { LOG_I("Creating device", 0); LOG_D("Device address: %p", this); initialize_device_struct(KEYMASTER_SOFTWARE_ONLY | KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_EC); } SoftKeymasterDevice::SoftKeymasterDevice(SoftKeymasterContext* context) : wrapped_km0_device_(nullptr), wrapped_km1_device_(nullptr), context_(context), impl_(new AndroidKeymaster(context_, kOperationTableSize)), configured_(false) { LOG_I("Creating test device", 0); LOG_D("Device address: %p", this); initialize_device_struct(KEYMASTER_SOFTWARE_ONLY | KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_EC); } keymaster_error_t SoftKeymasterDevice::SetHardwareDevice(keymaster0_device_t* keymaster0_device) { assert(keymaster0_device); LOG_D("Reinitializing SoftKeymasterDevice to use HW keymaster0", 0); if (!context_) return KM_ERROR_UNEXPECTED_NULL_POINTER; keymaster_error_t error = context_->SetHardwareDevice(keymaster0_device); if (error != KM_ERROR_OK) return error; initialize_device_struct(keymaster0_device->flags); module_name_ = km1_device_.common.module->name; module_name_.append("(Wrapping "); module_name_.append(keymaster0_device->common.module->name); module_name_.append(")"); updated_module_ = *km1_device_.common.module; updated_module_.name = module_name_.c_str(); km1_device_.common.module = &updated_module_; wrapped_km0_device_ = keymaster0_device; wrapped_km1_device_ = nullptr; return KM_ERROR_OK; } keymaster_error_t SoftKeymasterDevice::SetHardwareDevice(keymaster1_device_t* keymaster1_device) { assert(keymaster1_device); LOG_D("Reinitializing SoftKeymasterDevice to use HW keymaster1", 0); if (!context_) return KM_ERROR_UNEXPECTED_NULL_POINTER; keymaster_error_t error = map_digests(keymaster1_device, &km1_device_digests_); if (error != KM_ERROR_OK) return error; error = context_->SetHardwareDevice(keymaster1_device); if (error != KM_ERROR_OK) return error; initialize_device_struct(keymaster1_device->flags); module_name_ = km1_device_.common.module->name; module_name_.append(" (Wrapping "); module_name_.append(keymaster1_device->common.module->name); module_name_.append(")"); updated_module_ = *km1_device_.common.module; updated_module_.name = module_name_.c_str(); km1_device_.common.module = &updated_module_; wrapped_km0_device_ = nullptr; wrapped_km1_device_ = keymaster1_device; return KM_ERROR_OK; } bool SoftKeymasterDevice::Keymaster1DeviceIsGood() { std::vector expected_rsa_digests = { KM_DIGEST_NONE, KM_DIGEST_MD5, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512}; std::vector expected_ec_digests = { KM_DIGEST_NONE, KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224, KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512}; for (auto& entry : km1_device_digests_) { if (entry.first.first == KM_ALGORITHM_RSA) if (!std::is_permutation(entry.second.begin(), entry.second.end(), expected_rsa_digests.begin())) return false; if (entry.first.first == KM_ALGORITHM_EC) if (!std::is_permutation(entry.second.begin(), entry.second.end(), expected_ec_digests.begin())) return false; } return true; } void SoftKeymasterDevice::initialize_device_struct(uint32_t flags) { memset(&km1_device_, 0, sizeof(km1_device_)); km1_device_.common.tag = HARDWARE_DEVICE_TAG; km1_device_.common.version = 1; km1_device_.common.module = reinterpret_cast(&soft_keymaster1_device_module); km1_device_.common.close = &close_device; km1_device_.flags = flags; km1_device_.context = this; // keymaster0 APIs km1_device_.generate_keypair = nullptr; km1_device_.import_keypair = nullptr; km1_device_.get_keypair_public = nullptr; km1_device_.delete_keypair = nullptr; km1_device_.delete_all = nullptr; km1_device_.sign_data = nullptr; km1_device_.verify_data = nullptr; // keymaster1 APIs km1_device_.get_supported_algorithms = get_supported_algorithms; km1_device_.get_supported_block_modes = get_supported_block_modes; km1_device_.get_supported_padding_modes = get_supported_padding_modes; km1_device_.get_supported_digests = get_supported_digests; km1_device_.get_supported_import_formats = get_supported_import_formats; km1_device_.get_supported_export_formats = get_supported_export_formats; km1_device_.add_rng_entropy = add_rng_entropy; km1_device_.generate_key = generate_key; km1_device_.get_key_characteristics = get_key_characteristics; km1_device_.import_key = import_key; km1_device_.export_key = export_key; km1_device_.delete_key = delete_key; km1_device_.delete_all_keys = delete_all_keys; km1_device_.begin = begin; km1_device_.update = update; km1_device_.finish = finish; km1_device_.abort = abort; // keymaster2 APIs memset(&km2_device_, 0, sizeof(km2_device_)); km2_device_.flags = flags; km2_device_.context = this; km2_device_.common.tag = HARDWARE_DEVICE_TAG; km2_device_.common.version = 1; km2_device_.common.module = reinterpret_cast(&soft_keymaster2_device_module); km2_device_.common.close = &close_device; km2_device_.configure = configure; km2_device_.add_rng_entropy = add_rng_entropy; km2_device_.generate_key = generate_key; km2_device_.get_key_characteristics = get_key_characteristics; km2_device_.import_key = import_key; km2_device_.export_key = export_key; km2_device_.attest_key = attest_key; km2_device_.upgrade_key = upgrade_key; km2_device_.delete_key = delete_key; km2_device_.delete_all_keys = delete_all_keys; km2_device_.begin = begin; km2_device_.update = update; km2_device_.finish = finish; km2_device_.abort = abort; } hw_device_t* SoftKeymasterDevice::hw_device() { return &km1_device_.common; } keymaster1_device_t* SoftKeymasterDevice::keymaster_device() { return &km1_device_; } keymaster2_device_t* SoftKeymasterDevice::keymaster2_device() { return &km2_device_; } namespace { keymaster_key_characteristics_t* BuildCharacteristics(const AuthorizationSet& hw_enforced, const AuthorizationSet& sw_enforced) { keymaster_key_characteristics_t* characteristics = reinterpret_cast( malloc(sizeof(keymaster_key_characteristics_t))); if (characteristics) { hw_enforced.CopyToParamSet(&characteristics->hw_enforced); sw_enforced.CopyToParamSet(&characteristics->sw_enforced); } return characteristics; } template void AddClientAndAppData(const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, RequestType* request) { request->additional_params.Clear(); if (client_id) request->additional_params.push_back(TAG_APPLICATION_ID, *client_id); if (app_data) request->additional_params.push_back(TAG_APPLICATION_DATA, *app_data); } template SoftKeymasterDevice* convert_device(const T* dev) { static_assert((std::is_same::value || std::is_same::value || std::is_same::value), "convert_device should only be applied to keymaster devices"); return reinterpret_cast(dev->context); } bool FindAlgorithm(const keymaster_key_param_set_t& params, keymaster_algorithm_t* algorithm) { for (size_t i = 0; i < params.length; ++i) if (params.params[i].tag == KM_TAG_ALGORITHM) { *algorithm = static_cast(params.params[i].enumerated); return true; } return false; } keymaster_error_t GetAlgorithm(const keymaster1_device_t* dev, const keymaster_key_blob_t& key, const AuthorizationSet& in_params, keymaster_algorithm_t* algorithm) { keymaster_blob_t client_id = {nullptr, 0}; keymaster_blob_t app_data = {nullptr, 0}; keymaster_blob_t* client_id_ptr = nullptr; keymaster_blob_t* app_data_ptr = nullptr; if (in_params.GetTagValue(TAG_APPLICATION_ID, &client_id)) client_id_ptr = &client_id; if (in_params.GetTagValue(TAG_APPLICATION_DATA, &app_data)) app_data_ptr = &app_data; keymaster_key_characteristics_t* characteristics; keymaster_error_t error = dev->get_key_characteristics(dev, &key, client_id_ptr, app_data_ptr, &characteristics); if (error != KM_ERROR_OK) return error; std::unique_ptr characteristics_deleter(characteristics); if (FindAlgorithm(characteristics->hw_enforced, algorithm)) return KM_ERROR_OK; if (FindAlgorithm(characteristics->sw_enforced, algorithm)) return KM_ERROR_OK; return KM_ERROR_INVALID_KEY_BLOB; } } // unnamed namespaced /* static */ int SoftKeymasterDevice::close_device(hw_device_t* dev) { switch (dev->module->module_api_version) { case KEYMASTER_MODULE_API_VERSION_2_0: { delete convert_device(reinterpret_cast(dev)); break; } case KEYMASTER_MODULE_API_VERSION_1_0: { delete convert_device(reinterpret_cast(dev)); break; } default: return -1; } return 0; } /* static */ keymaster_error_t SoftKeymasterDevice::get_supported_algorithms(const keymaster1_device_t* dev, keymaster_algorithm_t** algorithms, size_t* algorithms_length) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!algorithms || !algorithms_length) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) return km1_dev->get_supported_algorithms(km1_dev, algorithms, algorithms_length); SupportedAlgorithmsRequest request; SupportedAlgorithmsResponse response; convert_device(dev)->impl_->SupportedAlgorithms(request, &response); if (response.error != KM_ERROR_OK) { LOG_E("get_supported_algorithms failed with %d", response.error); return response.error; } *algorithms_length = response.results_length; *algorithms = reinterpret_cast(malloc(*algorithms_length * sizeof(**algorithms))); if (!*algorithms) return KM_ERROR_MEMORY_ALLOCATION_FAILED; std::copy(response.results, response.results + response.results_length, *algorithms); return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::get_supported_block_modes(const keymaster1_device_t* dev, keymaster_algorithm_t algorithm, keymaster_purpose_t purpose, keymaster_block_mode_t** modes, size_t* modes_length) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!modes || !modes_length) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) return km1_dev->get_supported_block_modes(km1_dev, algorithm, purpose, modes, modes_length); SupportedBlockModesRequest request; request.algorithm = algorithm; request.purpose = purpose; SupportedBlockModesResponse response; convert_device(dev)->impl_->SupportedBlockModes(request, &response); if (response.error != KM_ERROR_OK) { LOG_E("get_supported_block_modes failed with %d", response.error); return response.error; } *modes_length = response.results_length; *modes = reinterpret_cast(malloc(*modes_length * sizeof(**modes))); if (!*modes) return KM_ERROR_MEMORY_ALLOCATION_FAILED; std::copy(response.results, response.results + response.results_length, *modes); return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::get_supported_padding_modes(const keymaster1_device_t* dev, keymaster_algorithm_t algorithm, keymaster_purpose_t purpose, keymaster_padding_t** modes, size_t* modes_length) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!modes || !modes_length) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) return km1_dev->get_supported_padding_modes(km1_dev, algorithm, purpose, modes, modes_length); SupportedPaddingModesRequest request; request.algorithm = algorithm; request.purpose = purpose; SupportedPaddingModesResponse response; convert_device(dev)->impl_->SupportedPaddingModes(request, &response); if (response.error != KM_ERROR_OK) { LOG_E("get_supported_padding_modes failed with %d", response.error); return response.error; } *modes_length = response.results_length; *modes = reinterpret_cast(malloc(*modes_length * sizeof(**modes))); if (!*modes) return KM_ERROR_MEMORY_ALLOCATION_FAILED; std::copy(response.results, response.results + response.results_length, *modes); return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::get_supported_digests(const keymaster1_device_t* dev, keymaster_algorithm_t algorithm, keymaster_purpose_t purpose, keymaster_digest_t** digests, size_t* digests_length) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!digests || !digests_length) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) return km1_dev->get_supported_digests(km1_dev, algorithm, purpose, digests, digests_length); SupportedDigestsRequest request; request.algorithm = algorithm; request.purpose = purpose; SupportedDigestsResponse response; convert_device(dev)->impl_->SupportedDigests(request, &response); if (response.error != KM_ERROR_OK) { LOG_E("get_supported_digests failed with %d", response.error); return response.error; } *digests_length = response.results_length; *digests = reinterpret_cast(malloc(*digests_length * sizeof(**digests))); if (!*digests) return KM_ERROR_MEMORY_ALLOCATION_FAILED; std::copy(response.results, response.results + response.results_length, *digests); return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::get_supported_import_formats( const keymaster1_device_t* dev, keymaster_algorithm_t algorithm, keymaster_key_format_t** formats, size_t* formats_length) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!formats || !formats_length) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) return km1_dev->get_supported_import_formats(km1_dev, algorithm, formats, formats_length); SupportedImportFormatsRequest request; request.algorithm = algorithm; SupportedImportFormatsResponse response; convert_device(dev)->impl_->SupportedImportFormats(request, &response); if (response.error != KM_ERROR_OK) { LOG_E("get_supported_import_formats failed with %d", response.error); return response.error; } *formats_length = response.results_length; *formats = reinterpret_cast(malloc(*formats_length * sizeof(**formats))); if (!*formats) return KM_ERROR_MEMORY_ALLOCATION_FAILED; std::copy(response.results, response.results + response.results_length, *formats); return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::get_supported_export_formats( const keymaster1_device_t* dev, keymaster_algorithm_t algorithm, keymaster_key_format_t** formats, size_t* formats_length) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!formats || !formats_length) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) return km1_dev->get_supported_export_formats(km1_dev, algorithm, formats, formats_length); SupportedExportFormatsRequest request; request.algorithm = algorithm; SupportedExportFormatsResponse response; convert_device(dev)->impl_->SupportedExportFormats(request, &response); if (response.error != KM_ERROR_OK) { LOG_E("get_supported_export_formats failed with %d", response.error); return response.error; } *formats_length = response.results_length; *formats = reinterpret_cast(malloc(*formats_length * sizeof(**formats))); if (!*formats) return KM_ERROR_MEMORY_ALLOCATION_FAILED; std::copy(response.results, response.results + *formats_length, *formats); return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::configure(const keymaster2_device_t* dev, const keymaster_key_param_set_t* params) { AuthorizationSet params_copy(*params); uint32_t os_version; uint32_t os_patchlevel; if (!params_copy.GetTagValue(TAG_OS_VERSION, &os_version) || !params_copy.GetTagValue(TAG_OS_PATCHLEVEL, &os_patchlevel)) { LOG_E("Configuration parameters must contain OS version and patch level", 0); return KM_ERROR_INVALID_ARGUMENT; } keymaster_error_t error = convert_device(dev)->context_->SetSystemVersion(os_version, os_patchlevel); if (error == KM_ERROR_OK) convert_device(dev)->configured_ = true; return error; } /* static */ keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster1_device_t* dev, const uint8_t* data, size_t data_length) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) return km1_dev->add_rng_entropy(km1_dev, data, data_length); AddEntropyRequest request; request.random_data.Reinitialize(data, data_length); AddEntropyResponse response; convert_device(dev)->impl_->AddRngEntropy(request, &response); if (response.error != KM_ERROR_OK) LOG_E("add_rng_entropy failed with %d", response.error); return response.error; } /* static */ keymaster_error_t SoftKeymasterDevice::add_rng_entropy(const keymaster2_device_t* dev, const uint8_t* data, size_t data_length) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; SoftKeymasterDevice* sk_dev = convert_device(dev); return add_rng_entropy(&sk_dev->km1_device_, data, data_length); } template bool contains(const Collection& c, const Value& v) { return std::find(c.begin(), c.end(), v) != c.end(); } bool SoftKeymasterDevice::FindUnsupportedDigest(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose, const AuthorizationSet& params, keymaster_digest_t* unsupported) const { assert(wrapped_km1_device_); auto supported_digests = km1_device_digests_.find(std::make_pair(algorithm, purpose)); if (supported_digests == km1_device_digests_.end()) // Invalid algorith/purpose pair (e.g. EC encrypt). Let the error be handled by HW module. return false; for (auto& entry : params) if (entry.tag == TAG_DIGEST) if (!contains(supported_digests->second, entry.enumerated)) { LOG_I("Digest %d requested but not supported by module %s", entry.enumerated, wrapped_km1_device_->common.module->name); *unsupported = static_cast(entry.enumerated); return true; } return false; } bool SoftKeymasterDevice::RequiresSoftwareDigesting(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose, const AuthorizationSet& params) const { assert(wrapped_km1_device_); if (!wrapped_km1_device_) return true; switch (algorithm) { case KM_ALGORITHM_AES: case KM_ALGORITHM_HMAC: LOG_D("Not performing software digesting for algorithm %d", algorithm); return false; case KM_ALGORITHM_RSA: case KM_ALGORITHM_EC: break; } keymaster_digest_t unsupported; if (!FindUnsupportedDigest(algorithm, purpose, params, &unsupported)) { LOG_D("Requested digest(s) supported for algorithm %d and purpose %d", algorithm, purpose); return false; } return true; } bool SoftKeymasterDevice::KeyRequiresSoftwareDigesting( const AuthorizationSet& key_description) const { assert(wrapped_km1_device_); if (!wrapped_km1_device_) return true; keymaster_algorithm_t algorithm; if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) { // The hardware module will return an error during keygen. return false; } for (auto& entry : key_description) if (entry.tag == TAG_PURPOSE) { keymaster_purpose_t purpose = static_cast(entry.enumerated); if (RequiresSoftwareDigesting(algorithm, purpose, key_description)) return true; } return false; } /* static */ keymaster_error_t SoftKeymasterDevice::generate_key( const keymaster1_device_t* dev, const keymaster_key_param_set_t* params, keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t** characteristics) { if (!dev || !params) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!key_blob) return KM_ERROR_OUTPUT_PARAMETER_NULL; SoftKeymasterDevice* sk_dev = convert_device(dev); GenerateKeyRequest request; request.key_description.Reinitialize(*params); keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_; if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description)) return km1_dev->generate_key(km1_dev, params, key_blob, characteristics); GenerateKeyResponse response; sk_dev->impl_->GenerateKey(request, &response); if (response.error != KM_ERROR_OK) return response.error; key_blob->key_material_size = response.key_blob.key_material_size; uint8_t* tmp = reinterpret_cast(malloc(key_blob->key_material_size)); if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED; memcpy(tmp, response.key_blob.key_material, response.key_blob.key_material_size); key_blob->key_material = tmp; if (characteristics) { // This is a keymaster1 method, and keymaster1 doesn't include version info, so remove it. response.enforced.erase(response.enforced.find(TAG_OS_VERSION)); response.enforced.erase(response.enforced.find(TAG_OS_PATCHLEVEL)); response.unenforced.erase(response.unenforced.find(TAG_OS_VERSION)); response.unenforced.erase(response.unenforced.find(TAG_OS_PATCHLEVEL)); *characteristics = BuildCharacteristics(response.enforced, response.unenforced); if (!*characteristics) return KM_ERROR_MEMORY_ALLOCATION_FAILED; } return KM_ERROR_OK; } keymaster_error_t SoftKeymasterDevice::generate_key(const keymaster2_device_t* dev, // const keymaster_key_param_set_t* params, keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; if (!key_blob) return KM_ERROR_OUTPUT_PARAMETER_NULL; SoftKeymasterDevice* sk_dev = convert_device(dev); GenerateKeyRequest request; request.key_description.Reinitialize(*params); keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_; if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description)) { keymaster_key_characteristics_t* chars_ptr; keymaster_error_t error = km1_dev->generate_key(km1_dev, params, key_blob, characteristics ? &chars_ptr : nullptr); if (error != KM_ERROR_OK) return error; if (characteristics) { *characteristics = *chars_ptr; free(chars_ptr); } return KM_ERROR_OK; } GenerateKeyResponse response; sk_dev->impl_->GenerateKey(request, &response); if (response.error != KM_ERROR_OK) return response.error; key_blob->key_material_size = response.key_blob.key_material_size; uint8_t* tmp = reinterpret_cast(malloc(key_blob->key_material_size)); if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED; memcpy(tmp, response.key_blob.key_material, response.key_blob.key_material_size); key_blob->key_material = tmp; if (characteristics) { response.enforced.CopyToParamSet(&characteristics->hw_enforced); response.unenforced.CopyToParamSet(&characteristics->sw_enforced); } return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::get_key_characteristics( const keymaster1_device_t* dev, const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, keymaster_key_characteristics_t** characteristics) { if (!dev || !key_blob || !key_blob->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!characteristics) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) { return km1_dev->get_key_characteristics(km1_dev, key_blob, client_id, app_data, characteristics); } GetKeyCharacteristicsRequest request; request.SetKeyMaterial(*key_blob); AddClientAndAppData(client_id, app_data, &request); GetKeyCharacteristicsResponse response; convert_device(dev)->impl_->GetKeyCharacteristics(request, &response); if (response.error != KM_ERROR_OK) return response.error; // This is a keymaster1 method, and keymaster1 doesn't include version info, so remove it. response.enforced.erase(response.enforced.find(TAG_OS_VERSION)); response.enforced.erase(response.enforced.find(TAG_OS_PATCHLEVEL)); response.unenforced.erase(response.unenforced.find(TAG_OS_VERSION)); response.unenforced.erase(response.unenforced.find(TAG_OS_PATCHLEVEL)); *characteristics = BuildCharacteristics(response.enforced, response.unenforced); if (!*characteristics) return KM_ERROR_MEMORY_ALLOCATION_FAILED; return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::get_key_characteristics( const keymaster2_device_t* dev, const keymaster_key_blob_t* key_blob, const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, keymaster_key_characteristics_t* characteristics) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; if (!characteristics) return KM_ERROR_OUTPUT_PARAMETER_NULL; SoftKeymasterDevice* sk_dev = convert_device(dev); const keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_; if (km1_dev) { keymaster_key_characteristics_t* tmp_characteristics; keymaster_error_t error = km1_dev->get_key_characteristics(km1_dev, key_blob, client_id, app_data, &tmp_characteristics); if (error == KM_ERROR_OK) { *characteristics = *tmp_characteristics; free(tmp_characteristics); } return error; } GetKeyCharacteristicsRequest request; request.SetKeyMaterial(*key_blob); AddClientAndAppData(client_id, app_data, &request); GetKeyCharacteristicsResponse response; sk_dev->impl_->GetKeyCharacteristics(request, &response); if (response.error != KM_ERROR_OK) return response.error; response.enforced.CopyToParamSet(&characteristics->hw_enforced); response.unenforced.CopyToParamSet(&characteristics->sw_enforced); return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::import_key( const keymaster1_device_t* dev, const keymaster_key_param_set_t* params, keymaster_key_format_t key_format, const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t** characteristics) { if (!params || !key_data) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!key_blob) return KM_ERROR_OUTPUT_PARAMETER_NULL; SoftKeymasterDevice* sk_dev = convert_device(dev); ImportKeyRequest request; request.key_description.Reinitialize(*params); keymaster1_device_t* km1_dev = sk_dev->wrapped_km1_device_; if (km1_dev && !sk_dev->KeyRequiresSoftwareDigesting(request.key_description)) return km1_dev->import_key(km1_dev, params, key_format, key_data, key_blob, characteristics); if (characteristics) *characteristics = nullptr; request.key_format = key_format; request.SetKeyMaterial(key_data->data, key_data->data_length); ImportKeyResponse response; convert_device(dev)->impl_->ImportKey(request, &response); if (response.error != KM_ERROR_OK) return response.error; key_blob->key_material_size = response.key_blob.key_material_size; key_blob->key_material = reinterpret_cast(malloc(key_blob->key_material_size)); if (!key_blob->key_material) return KM_ERROR_MEMORY_ALLOCATION_FAILED; memcpy(const_cast(key_blob->key_material), response.key_blob.key_material, response.key_blob.key_material_size); if (characteristics) { *characteristics = BuildCharacteristics(response.enforced, response.unenforced); if (!*characteristics) return KM_ERROR_MEMORY_ALLOCATION_FAILED; } return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::import_key( const keymaster2_device_t* dev, const keymaster_key_param_set_t* params, keymaster_key_format_t key_format, const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; SoftKeymasterDevice* sk_dev = convert_device(dev); keymaster_error_t error; if (characteristics) { keymaster_key_characteristics_t* characteristics_ptr; error = import_key(&sk_dev->km1_device_, params, key_format, key_data, key_blob, &characteristics_ptr); if (error == KM_ERROR_OK) { *characteristics = *characteristics_ptr; free(characteristics_ptr); } } else { error = import_key(&sk_dev->km1_device_, params, key_format, key_data, key_blob, nullptr); } return error; } /* static */ keymaster_error_t SoftKeymasterDevice::export_key(const keymaster1_device_t* dev, keymaster_key_format_t export_format, const keymaster_key_blob_t* key_to_export, const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, keymaster_blob_t* export_data) { if (!key_to_export || !key_to_export->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!export_data) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) return km1_dev->export_key(km1_dev, export_format, key_to_export, client_id, app_data, export_data); export_data->data = nullptr; export_data->data_length = 0; ExportKeyRequest request; request.key_format = export_format; request.SetKeyMaterial(*key_to_export); AddClientAndAppData(client_id, app_data, &request); ExportKeyResponse response; convert_device(dev)->impl_->ExportKey(request, &response); if (response.error != KM_ERROR_OK) return response.error; export_data->data_length = response.key_data_length; uint8_t* tmp = reinterpret_cast(malloc(export_data->data_length)); if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED; memcpy(tmp, response.key_data, export_data->data_length); export_data->data = tmp; return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::export_key(const keymaster2_device_t* dev, keymaster_key_format_t export_format, const keymaster_key_blob_t* key_to_export, const keymaster_blob_t* client_id, const keymaster_blob_t* app_data, keymaster_blob_t* export_data) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; SoftKeymasterDevice* sk_dev = convert_device(dev); return export_key(&sk_dev->km1_device_, export_format, key_to_export, client_id, app_data, export_data); } /* static */ keymaster_error_t SoftKeymasterDevice::attest_key(const keymaster2_device_t* dev, const keymaster_key_blob_t* key_to_attest, const keymaster_key_param_set_t* attest_params, keymaster_cert_chain_t* cert_chain) { if (!dev || !key_to_attest || !attest_params || !cert_chain) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; cert_chain->entry_count = 0; cert_chain->entries = nullptr; AttestKeyRequest request; request.SetKeyMaterial(*key_to_attest); request.attest_params.Reinitialize(*attest_params); keymaster_blob_t attestation_challenge = {}; request.attest_params.GetTagValue(TAG_ATTESTATION_CHALLENGE, &attestation_challenge); if (attestation_challenge.data_length > kMaximumAttestationChallengeLength) { LOG_E("%d-byte attestation challenge; only %d bytes allowed", attestation_challenge.data_length, kMaximumAttestationChallengeLength); return KM_ERROR_INVALID_INPUT_LENGTH; } AttestKeyResponse response; convert_device(dev)->impl_->AttestKey(request, &response); if (response.error != KM_ERROR_OK) return response.error; // Allocate and clear storage for cert_chain. keymaster_cert_chain_t& rsp_chain = response.certificate_chain; cert_chain->entries = reinterpret_cast( malloc(rsp_chain.entry_count * sizeof(*cert_chain->entries))); if (!cert_chain->entries) return KM_ERROR_MEMORY_ALLOCATION_FAILED; cert_chain->entry_count = rsp_chain.entry_count; for (keymaster_blob_t& entry : array_range(cert_chain->entries, cert_chain->entry_count)) entry = {}; // Copy cert_chain contents size_t i = 0; for (keymaster_blob_t& entry : array_range(rsp_chain.entries, rsp_chain.entry_count)) { cert_chain->entries[i].data = reinterpret_cast(malloc(entry.data_length)); if (!cert_chain->entries[i].data) { keymaster_free_cert_chain(cert_chain); return KM_ERROR_MEMORY_ALLOCATION_FAILED; } cert_chain->entries[i].data_length = entry.data_length; memcpy(const_cast(cert_chain->entries[i].data), entry.data, entry.data_length); ++i; } return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::upgrade_key(const keymaster2_device_t* dev, const keymaster_key_blob_t* key_to_upgrade, const keymaster_key_param_set_t* upgrade_params, keymaster_key_blob_t* upgraded_key) { if (!dev || !key_to_upgrade || !upgrade_params) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!upgraded_key) return KM_ERROR_OUTPUT_PARAMETER_NULL; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; UpgradeKeyRequest request; request.SetKeyMaterial(*key_to_upgrade); request.upgrade_params.Reinitialize(*upgrade_params); UpgradeKeyResponse response; convert_device(dev)->impl_->UpgradeKey(request, &response); if (response.error != KM_ERROR_OK) return response.error; upgraded_key->key_material_size = response.upgraded_key.key_material_size; uint8_t* tmp = reinterpret_cast(malloc(upgraded_key->key_material_size)); if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED; memcpy(tmp, response.upgraded_key.key_material, response.upgraded_key.key_material_size); upgraded_key->key_material = tmp; return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::delete_key(const keymaster1_device_t* dev, const keymaster_key_blob_t* key) { if (!dev || !key || !key->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER; KeymasterKeyBlob blob(*key); return convert_device(dev)->context_->DeleteKey(blob); } /* static */ keymaster_error_t SoftKeymasterDevice::delete_key(const keymaster2_device_t* dev, const keymaster_key_blob_t* key) { if (!dev || !key || !key->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; KeymasterKeyBlob blob(*key); return convert_device(dev)->context_->DeleteKey(blob); } /* static */ keymaster_error_t SoftKeymasterDevice::delete_all_keys(const keymaster1_device_t* dev) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; return convert_device(dev)->context_->DeleteAllKeys(); } /* static */ keymaster_error_t SoftKeymasterDevice::delete_all_keys(const keymaster2_device_t* dev) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; return convert_device(dev)->context_->DeleteAllKeys(); } /* static */ keymaster_error_t SoftKeymasterDevice::begin(const keymaster1_device_t* dev, keymaster_purpose_t purpose, const keymaster_key_blob_t* key, const keymaster_key_param_set_t* in_params, keymaster_key_param_set_t* out_params, keymaster_operation_handle_t* operation_handle) { if (!key || !key->key_material) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!operation_handle) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev) { AuthorizationSet in_params_set(*in_params); keymaster_algorithm_t algorithm = KM_ALGORITHM_AES; keymaster_error_t error = GetAlgorithm(km1_dev, *key, in_params_set, &algorithm); if (error != KM_ERROR_OK) return error; if (!convert_device(dev)->RequiresSoftwareDigesting(algorithm, purpose, in_params_set)) { LOG_D("Operation supported by %s, passing through to keymaster1 module", km1_dev->common.module->name); return km1_dev->begin(km1_dev, purpose, key, in_params, out_params, operation_handle); } LOG_I("Doing software digesting for keymaster1 module %s", km1_dev->common.module->name); } if (out_params) { out_params->params = nullptr; out_params->length = 0; } BeginOperationRequest request; request.purpose = purpose; request.SetKeyMaterial(*key); request.additional_params.Reinitialize(*in_params); BeginOperationResponse response; convert_device(dev)->impl_->BeginOperation(request, &response); if (response.error != KM_ERROR_OK) return response.error; if (response.output_params.size() > 0) { if (out_params) response.output_params.CopyToParamSet(out_params); else return KM_ERROR_OUTPUT_PARAMETER_NULL; } *operation_handle = response.op_handle; return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::begin(const keymaster2_device_t* dev, keymaster_purpose_t purpose, const keymaster_key_blob_t* key, const keymaster_key_param_set_t* in_params, keymaster_key_param_set_t* out_params, keymaster_operation_handle_t* operation_handle) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; SoftKeymasterDevice* sk_dev = convert_device(dev); return begin(&sk_dev->km1_device_, purpose, key, in_params, out_params, operation_handle); } /* static */ keymaster_error_t SoftKeymasterDevice::update(const keymaster1_device_t* dev, keymaster_operation_handle_t operation_handle, const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input, size_t* input_consumed, keymaster_key_param_set_t* out_params, keymaster_blob_t* output) { if (!input) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!input_consumed) return KM_ERROR_OUTPUT_PARAMETER_NULL; const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) { // This operation is being handled by km1_dev (or doesn't exist). Pass it through to // km1_dev. Otherwise, we'll use the software AndroidKeymaster, which may delegate to // km1_dev after doing necessary digesting. return km1_dev->update(km1_dev, operation_handle, in_params, input, input_consumed, out_params, output); } if (out_params) { out_params->params = nullptr; out_params->length = 0; } if (output) { output->data = nullptr; output->data_length = 0; } UpdateOperationRequest request; request.op_handle = operation_handle; if (input) request.input.Reinitialize(input->data, input->data_length); if (in_params) request.additional_params.Reinitialize(*in_params); UpdateOperationResponse response; convert_device(dev)->impl_->UpdateOperation(request, &response); if (response.error != KM_ERROR_OK) return response.error; if (response.output_params.size() > 0) { if (out_params) response.output_params.CopyToParamSet(out_params); else return KM_ERROR_OUTPUT_PARAMETER_NULL; } *input_consumed = response.input_consumed; if (output) { output->data_length = response.output.available_read(); uint8_t* tmp = reinterpret_cast(malloc(output->data_length)); if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED; memcpy(tmp, response.output.peek_read(), output->data_length); output->data = tmp; } else if (response.output.available_read() > 0) { return KM_ERROR_OUTPUT_PARAMETER_NULL; } return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::update(const keymaster2_device_t* dev, keymaster_operation_handle_t operation_handle, const keymaster_key_param_set_t* in_params, const keymaster_blob_t* input, size_t* input_consumed, keymaster_key_param_set_t* out_params, keymaster_blob_t* output) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; SoftKeymasterDevice* sk_dev = convert_device(dev); return update(&sk_dev->km1_device_, operation_handle, in_params, input, input_consumed, out_params, output); } /* static */ keymaster_error_t SoftKeymasterDevice::finish(const keymaster1_device_t* dev, keymaster_operation_handle_t operation_handle, const keymaster_key_param_set_t* params, const keymaster_blob_t* signature, keymaster_key_param_set_t* out_params, keymaster_blob_t* output) { const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) { // This operation is being handled by km1_dev (or doesn't exist). Pass it through to // km1_dev. Otherwise, we'll use the software AndroidKeymaster, which may delegate to // km1_dev after doing necessary digesting. return km1_dev->finish(km1_dev, operation_handle, params, signature, out_params, output); } if (out_params) { out_params->params = nullptr; out_params->length = 0; } if (output) { output->data = nullptr; output->data_length = 0; } FinishOperationRequest request; request.op_handle = operation_handle; if (signature && signature->data_length > 0) request.signature.Reinitialize(signature->data, signature->data_length); request.additional_params.Reinitialize(*params); FinishOperationResponse response; convert_device(dev)->impl_->FinishOperation(request, &response); if (response.error != KM_ERROR_OK) return response.error; if (response.output_params.size() > 0) { if (out_params) response.output_params.CopyToParamSet(out_params); else return KM_ERROR_OUTPUT_PARAMETER_NULL; } if (output) { output->data_length = response.output.available_read(); uint8_t* tmp = reinterpret_cast(malloc(output->data_length)); if (!tmp) return KM_ERROR_MEMORY_ALLOCATION_FAILED; memcpy(tmp, response.output.peek_read(), output->data_length); output->data = tmp; } else if (response.output.available_read() > 0) { return KM_ERROR_OUTPUT_PARAMETER_NULL; } return KM_ERROR_OK; } /* static */ keymaster_error_t SoftKeymasterDevice::finish(const keymaster2_device_t* dev, keymaster_operation_handle_t operation_handle, const keymaster_key_param_set_t* params, const keymaster_blob_t* input, const keymaster_blob_t* signature, keymaster_key_param_set_t* out_params, keymaster_blob_t* output) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; if (input && input->data) return KM_ERROR_UNIMPLEMENTED; // TODO(swillden): Implement this SoftKeymasterDevice* sk_dev = convert_device(dev); return finish(&sk_dev->km1_device_, operation_handle, params, signature, out_params, output); } /* static */ keymaster_error_t SoftKeymasterDevice::abort(const keymaster1_device_t* dev, keymaster_operation_handle_t operation_handle) { const keymaster1_device_t* km1_dev = convert_device(dev)->wrapped_km1_device_; if (km1_dev && !convert_device(dev)->impl_->has_operation(operation_handle)) { // This operation is being handled by km1_dev (or doesn't exist). Pass it through to // km1_dev. Otherwise, we'll use the software AndroidKeymaster, which may delegate to // km1_dev. return km1_dev->abort(km1_dev, operation_handle); } AbortOperationRequest request; request.op_handle = operation_handle; AbortOperationResponse response; convert_device(dev)->impl_->AbortOperation(request, &response); return response.error; } /* static */ keymaster_error_t SoftKeymasterDevice::abort(const keymaster2_device_t* dev, keymaster_operation_handle_t operation_handle) { if (!dev) return KM_ERROR_UNEXPECTED_NULL_POINTER; if (!convert_device(dev)->configured()) return KM_ERROR_KEYMASTER_NOT_CONFIGURED; SoftKeymasterDevice* sk_dev = convert_device(dev); return abort(&sk_dev->km1_device_, operation_handle); } /* static */ void SoftKeymasterDevice::StoreDefaultNewKeyParams(keymaster_algorithm_t algorithm, AuthorizationSet* auth_set) { auth_set->push_back(TAG_PURPOSE, KM_PURPOSE_SIGN); auth_set->push_back(TAG_PURPOSE, KM_PURPOSE_VERIFY); auth_set->push_back(TAG_ALL_USERS); auth_set->push_back(TAG_NO_AUTH_REQUIRED); // All digests. auth_set->push_back(TAG_DIGEST, KM_DIGEST_NONE); auth_set->push_back(TAG_DIGEST, KM_DIGEST_MD5); auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA1); auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA_2_224); auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA_2_256); auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA_2_384); auth_set->push_back(TAG_DIGEST, KM_DIGEST_SHA_2_512); if (algorithm == KM_ALGORITHM_RSA) { auth_set->push_back(TAG_PURPOSE, KM_PURPOSE_ENCRYPT); auth_set->push_back(TAG_PURPOSE, KM_PURPOSE_DECRYPT); auth_set->push_back(TAG_PADDING, KM_PAD_NONE); auth_set->push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN); auth_set->push_back(TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_ENCRYPT); auth_set->push_back(TAG_PADDING, KM_PAD_RSA_PSS); auth_set->push_back(TAG_PADDING, KM_PAD_RSA_OAEP); } } } // namespace keymaster