/* * Copyright (C) 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. */ #include "Keymaster.h" #include namespace android { namespace vold { bool KeymasterOperation::updateCompletely( const std::string &input, std::string *output) { output->clear(); auto it = input.begin(); while (it != input.end()) { size_t toRead = static_cast(input.end() - it); keymaster_blob_t inputBlob {reinterpret_cast(&*it), toRead}; keymaster_blob_t outputBlob; size_t inputConsumed; auto error = mDevice->update(mDevice, mOpHandle, nullptr, &inputBlob, &inputConsumed, nullptr, &outputBlob); if (error != KM_ERROR_OK) { LOG(ERROR) << "update failed, code " << error; mDevice = nullptr; return false; } output->append(reinterpret_cast(outputBlob.data), outputBlob.data_length); free(const_cast(outputBlob.data)); if (inputConsumed > toRead) { LOG(ERROR) << "update reported too much input consumed"; mDevice = nullptr; return false; } it += inputConsumed; } return true; } bool KeymasterOperation::finish() { auto error = mDevice->finish(mDevice, mOpHandle, nullptr, nullptr, nullptr, nullptr); mDevice = nullptr; if (error != KM_ERROR_OK) { LOG(ERROR) << "finish failed, code " << error; return false; } return true; } bool KeymasterOperation::finishWithOutput(std::string *output) { keymaster_blob_t outputBlob; auto error = mDevice->finish(mDevice, mOpHandle, nullptr, nullptr, nullptr, &outputBlob); mDevice = nullptr; if (error != KM_ERROR_OK) { LOG(ERROR) << "finish failed, code " << error; return false; } output->assign(reinterpret_cast(outputBlob.data), outputBlob.data_length); free(const_cast(outputBlob.data)); return true; } Keymaster::Keymaster() { mDevice = nullptr; const hw_module_t *module; int ret = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &module); if (ret != 0) { LOG(ERROR) << "hw_get_module_by_class returned " << ret; return; } // TODO: This will need to be updated to support keymaster2. if (module->module_api_version != KEYMASTER_MODULE_API_VERSION_1_0) { LOG(ERROR) << "module_api_version is " << module->module_api_version; return; } ret = keymaster1_open(module, &mDevice); if (ret != 0) { LOG(ERROR) << "keymaster1_open returned " << ret; mDevice = nullptr; return; } } bool Keymaster::generateKey( const keymaster::AuthorizationSet &inParams, std::string *key) { keymaster_key_blob_t keyBlob; auto error = mDevice->generate_key(mDevice, &inParams, &keyBlob, nullptr); if (error != KM_ERROR_OK) { LOG(ERROR) << "generate_key failed, code " << error; return false; } key->assign(reinterpret_cast(keyBlob.key_material), keyBlob.key_material_size); free(const_cast(keyBlob.key_material)); return true; } bool Keymaster::deleteKey(const std::string &key) { if (mDevice->delete_key == nullptr) return true; keymaster_key_blob_t keyBlob { reinterpret_cast(key.data()), key.size() }; auto error = mDevice->delete_key(mDevice, &keyBlob); if (error != KM_ERROR_OK) { LOG(ERROR) << "delete_key failed, code " << error; return false; } return true; } KeymasterOperation Keymaster::begin( keymaster_purpose_t purpose, const std::string &key, const keymaster::AuthorizationSet &inParams, keymaster::AuthorizationSet *outParams) { keymaster_key_blob_t keyBlob { reinterpret_cast(key.data()), key.size() }; keymaster_operation_handle_t mOpHandle; keymaster_key_param_set_t outParams_set; auto error = mDevice->begin(mDevice, purpose, &keyBlob, &inParams, &outParams_set, &mOpHandle); if (error != KM_ERROR_OK) { LOG(ERROR) << "begin failed, code " << error; return KeymasterOperation(nullptr, mOpHandle); } outParams->Clear(); outParams->push_back(outParams_set); keymaster_free_param_set(&outParams_set); return KeymasterOperation(mDevice, mOpHandle); } KeymasterOperation Keymaster::begin( keymaster_purpose_t purpose, const std::string &key, const keymaster::AuthorizationSet &inParams) { keymaster_key_blob_t keyBlob { reinterpret_cast(key.data()), key.size() }; keymaster_operation_handle_t mOpHandle; auto error = mDevice->begin(mDevice, purpose, &keyBlob, &inParams, nullptr, &mOpHandle); if (error != KM_ERROR_OK) { LOG(ERROR) << "begin failed, code " << error; return KeymasterOperation(nullptr, mOpHandle); } return KeymasterOperation(mDevice, mOpHandle); } } // namespace vold } // namespace android