blob: 9cc5b2b76e51a552edfceaec813b5e81d719f444 [file] [log] [blame]
dianlujitao47d41f62019-10-06 12:04:33 +08001/*
2 * Copyright (C) 2019 The LineageOS Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "vendor.qti.hardware.cryptfshw@1.0-impl-qti.qsee"
18
19#include "QSEEComController.h"
20
21#include <CryptfsHwUtils.h>
22#include <Types.h>
23#include <android-base/logging.h>
24#include <android-base/properties.h>
25#include <dlfcn.h>
26
27#include <thread>
28
29namespace {
30constexpr char kFilename[] = "libQSEEComAPI.so";
31
32#ifdef WAIT_FOR_QSEE
33bool IsQseecomUp() {
34 using namespace std::chrono_literals;
35 for (size_t i = 0; i < CRYPTFS_HW_UP_CHECK_COUNT; i++) {
36 if (::android::base::GetBoolProperty("sys.keymaster.loaded", false)) {
37 return true;
38 }
39 std::this_thread::sleep_for(100ms);
40 }
41
42 LOG(ERROR) << "Timed out waiting for QSEECom";
43 return false;
44}
45#endif
46} // anonymous namespace
47
48namespace vendor {
49namespace qti {
50namespace hardware {
51namespace cryptfshw {
52namespace V1_0 {
53namespace implementation {
54namespace qsee {
55
56Controller::Controller() {
57 std::shared_ptr<void> handle(dlopen(kFilename, RTLD_LAZY | RTLD_LOCAL), [this](void* p) {
58 mFn_create_key = nullptr;
59 mFn_update_key_user_info = nullptr;
60 mFn_wipe_key = nullptr;
61
62 if (p != nullptr) {
63 int err = dlclose(p);
64 p = nullptr;
65 if (err != 0) {
66 LOG(ERROR) << "FAILED TO CLOSE LIBRARY " << kFilename;
67 }
68 }
69 });
70 if (handle == nullptr) {
71 LOG(ERROR) << "FAILED TO LOAD LIBRARY " << kFilename << ": " << dlerror();
72 return;
73 }
74
75#ifdef WAIT_FOR_QSEE
76 if (!IsQseecomUp()) {
77 LOG_TO(SYSTEM, ERROR)
78 << "Timed out waiting for QSEECom listeners. Aborting FDE key operation";
79 return;
80 }
81#endif
82
83 handle_ = handle;
84 mFn_create_key = loadFunction<int (*)(int, void*)>("QSEECom_create_key");
85 mFn_update_key_user_info =
86 loadFunction<int (*)(int, void*, void*)>("QSEECom_update_key_user_info");
87 mFn_wipe_key = loadFunction<int (*)(int)>("QSEECom_wipe_key");
88}
89
90template <typename Function>
91Function Controller::loadFunction(const char* name) {
92 void* fn = dlsym(handle_.get(), name);
93 if (fn == nullptr) {
94 LOG(ERROR) << "loadFunction -- failed to load function " << name;
95 }
96 return reinterpret_cast<Function>(fn);
97}
98
99int Controller::createKey(int usage, const char* passwd) {
100 int32_t ret;
101 unsigned char hash32[MAX_PASSWORD_LEN];
102
103 if (mFn_create_key == nullptr) return CRYPTFS_HW_UPDATE_KEY_FAILED;
104
105 GetTmpPasswd(passwd, hash32, MAX_PASSWORD_LEN);
106
107 ret = mFn_create_key(usage, hash32);
108 if (ret) {
109 LOG_TO(SYSTEM, ERROR) << "Error::Qseecom call to create encryption key for usage " << usage
110 << " failed with ret = " << ret << ", errno = " << errno;
111 if (errno == ERANGE) {
112 ret = CRYPTFS_HW_KMS_MAX_FAILURE;
113 } else {
114 ret = CRYPTFS_HW_CREATE_KEY_FAILED;
115 }
116 } else {
117 LOG_TO(SYSTEM, ERROR) << "SUCESS::Qseecom call to create encryption key for usage " << usage
118 << " success with ret = " << ret;
119 }
120
121 secure_memset(hash32, 0, MAX_PASSWORD_LEN);
122
123 return ret;
124}
125
126int Controller::updateKey(int usage, const char* oldpw, const char* newpw) {
127 int32_t ret;
128 unsigned char current_hash32[MAX_PASSWORD_LEN], new_hash32[MAX_PASSWORD_LEN];
129
130 if (mFn_update_key_user_info == nullptr) return CRYPTFS_HW_UPDATE_KEY_FAILED;
131
132 GetTmpPasswd(oldpw, current_hash32, MAX_PASSWORD_LEN);
133 GetTmpPasswd(newpw, new_hash32, MAX_PASSWORD_LEN);
134
135 ret = mFn_update_key_user_info(usage, current_hash32, new_hash32);
136 if (ret) {
137 LOG_TO(SYSTEM, ERROR) << "Error::Qseecom call to update the encryption key for usage "
138 << usage << " failed with ret = " << ret << ", errno = " << errno;
139 if (errno == ERANGE) {
140 ret = CRYPTFS_HW_KMS_MAX_FAILURE;
141 } else {
142 ret = CRYPTFS_HW_UPDATE_KEY_FAILED;
143 }
144 } else {
145 LOG_TO(SYSTEM, ERROR) << "SUCCESS::Qseecom call to update the encryption key for usage "
146 << usage << " success with ret = " << ret;
147 }
148
149 secure_memset(current_hash32, 0, MAX_PASSWORD_LEN);
150 secure_memset(new_hash32, 0, MAX_PASSWORD_LEN);
151
152 return ret;
153}
154
155int Controller::wipeKey(int usage) {
156 int32_t ret;
157
158 if (mFn_wipe_key == nullptr) return CRYPTFS_HW_UPDATE_KEY_FAILED;
159
160 ret = mFn_wipe_key(usage);
161 if (ret) {
162 LOG_TO(SYSTEM, ERROR) << "Error::Qseecom call to wipe the encryption key for usage "
163 << usage << " failed with ret = " << ret << ", errno = " << errno;
164 ret = CRYPTFS_HW_WIPE_KEY_FAILED;
165 } else {
166 LOG_TO(SYSTEM, ERROR) << "SUCCESS::Qseecom call to wipe the encryption key for usage "
167 << usage << " success with ret = " << ret;
168 }
169 return ret;
170}
171
172} // namespace qsee
173} // namespace implementation
174} // namespace V1_0
175} // namespace cryptfshw
176} // namespace hardware
177} // namespace qti
178} // namespace vendor