summaryrefslogtreecommitdiffstats
path: root/cryptfshw/1.0/qsee/QSEEComController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cryptfshw/1.0/qsee/QSEEComController.cpp')
-rw-r--r--cryptfshw/1.0/qsee/QSEEComController.cpp178
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