diff options
Diffstat (limited to 'cryptfshw/1.0/qsee/QSEEComController.cpp')
-rw-r--r-- | cryptfshw/1.0/qsee/QSEEComController.cpp | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/cryptfshw/1.0/qsee/QSEEComController.cpp b/cryptfshw/1.0/qsee/QSEEComController.cpp new file mode 100644 index 0000000..9cc5b2b --- /dev/null +++ b/cryptfshw/1.0/qsee/QSEEComController.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2019 The LineageOS 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 "vendor.qti.hardware.cryptfshw@1.0-impl-qti.qsee" + +#include "QSEEComController.h" + +#include <CryptfsHwUtils.h> +#include <Types.h> +#include <android-base/logging.h> +#include <android-base/properties.h> +#include <dlfcn.h> + +#include <thread> + +namespace { +constexpr char kFilename[] = "libQSEEComAPI.so"; + +#ifdef WAIT_FOR_QSEE +bool IsQseecomUp() { + using namespace std::chrono_literals; + for (size_t i = 0; i < CRYPTFS_HW_UP_CHECK_COUNT; i++) { + if (::android::base::GetBoolProperty("sys.keymaster.loaded", false)) { + return true; + } + std::this_thread::sleep_for(100ms); + } + + LOG(ERROR) << "Timed out waiting for QSEECom"; + return false; +} +#endif +} // anonymous namespace + +namespace vendor { +namespace qti { +namespace hardware { +namespace cryptfshw { +namespace V1_0 { +namespace implementation { +namespace qsee { + +Controller::Controller() { + std::shared_ptr<void> handle(dlopen(kFilename, RTLD_LAZY | RTLD_LOCAL), [this](void* p) { + mFn_create_key = nullptr; + mFn_update_key_user_info = nullptr; + mFn_wipe_key = nullptr; + + if (p != nullptr) { + int err = dlclose(p); + p = nullptr; + if (err != 0) { + LOG(ERROR) << "FAILED TO CLOSE LIBRARY " << kFilename; + } + } + }); + if (handle == nullptr) { + LOG(ERROR) << "FAILED TO LOAD LIBRARY " << kFilename << ": " << dlerror(); + return; + } + +#ifdef WAIT_FOR_QSEE + if (!IsQseecomUp()) { + LOG_TO(SYSTEM, ERROR) + << "Timed out waiting for QSEECom listeners. Aborting FDE key operation"; + return; + } +#endif + + handle_ = handle; + mFn_create_key = loadFunction<int (*)(int, void*)>("QSEECom_create_key"); + mFn_update_key_user_info = + loadFunction<int (*)(int, void*, void*)>("QSEECom_update_key_user_info"); + mFn_wipe_key = loadFunction<int (*)(int)>("QSEECom_wipe_key"); +} + +template <typename Function> +Function Controller::loadFunction(const char* name) { + void* fn = dlsym(handle_.get(), name); + if (fn == nullptr) { + LOG(ERROR) << "loadFunction -- failed to load function " << name; + } + return reinterpret_cast<Function>(fn); +} + +int Controller::createKey(int usage, const char* passwd) { + int32_t ret; + unsigned char hash32[MAX_PASSWORD_LEN]; + + if (mFn_create_key == nullptr) return CRYPTFS_HW_UPDATE_KEY_FAILED; + + GetTmpPasswd(passwd, hash32, MAX_PASSWORD_LEN); + + ret = mFn_create_key(usage, hash32); + if (ret) { + LOG_TO(SYSTEM, ERROR) << "Error::Qseecom call to create encryption key for usage " << usage + << " failed with ret = " << ret << ", errno = " << errno; + if (errno == ERANGE) { + ret = CRYPTFS_HW_KMS_MAX_FAILURE; + } else { + ret = CRYPTFS_HW_CREATE_KEY_FAILED; + } + } else { + LOG_TO(SYSTEM, ERROR) << "SUCESS::Qseecom call to create encryption key for usage " << usage + << " success with ret = " << ret; + } + + secure_memset(hash32, 0, MAX_PASSWORD_LEN); + + return ret; +} + +int Controller::updateKey(int usage, const char* oldpw, const char* newpw) { + int32_t ret; + unsigned char current_hash32[MAX_PASSWORD_LEN], new_hash32[MAX_PASSWORD_LEN]; + + if (mFn_update_key_user_info == nullptr) return CRYPTFS_HW_UPDATE_KEY_FAILED; + + GetTmpPasswd(oldpw, current_hash32, MAX_PASSWORD_LEN); + GetTmpPasswd(newpw, new_hash32, MAX_PASSWORD_LEN); + + ret = mFn_update_key_user_info(usage, current_hash32, new_hash32); + if (ret) { + LOG_TO(SYSTEM, ERROR) << "Error::Qseecom call to update the encryption key for usage " + << usage << " failed with ret = " << ret << ", errno = " << errno; + if (errno == ERANGE) { + ret = CRYPTFS_HW_KMS_MAX_FAILURE; + } else { + ret = CRYPTFS_HW_UPDATE_KEY_FAILED; + } + } else { + LOG_TO(SYSTEM, ERROR) << "SUCCESS::Qseecom call to update the encryption key for usage " + << usage << " success with ret = " << ret; + } + + secure_memset(current_hash32, 0, MAX_PASSWORD_LEN); + secure_memset(new_hash32, 0, MAX_PASSWORD_LEN); + + return ret; +} + +int Controller::wipeKey(int usage) { + int32_t ret; + + if (mFn_wipe_key == nullptr) return CRYPTFS_HW_UPDATE_KEY_FAILED; + + ret = mFn_wipe_key(usage); + if (ret) { + LOG_TO(SYSTEM, ERROR) << "Error::Qseecom call to wipe the encryption key for usage " + << usage << " failed with ret = " << ret << ", errno = " << errno; + ret = CRYPTFS_HW_WIPE_KEY_FAILED; + } else { + LOG_TO(SYSTEM, ERROR) << "SUCCESS::Qseecom call to wipe the encryption key for usage " + << usage << " success with ret = " << ret; + } + return ret; +} + +} // namespace qsee +} // namespace implementation +} // namespace V1_0 +} // namespace cryptfshw +} // namespace hardware +} // namespace qti +} // namespace vendor |