blob: 9cc5b2b76e51a552edfceaec813b5e81d719f444 [file] [log] [blame]
/*
* 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