1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define LOG_TAG "SECURITYMANAGER"
16 #include "security_manager.h"
17 #include <limits>
18 #include <random>
19 #include <unistd.h>
20 #include "log_print.h"
21 #include "hks_api.h"
22 #include "hks_param.h"
23 #include "file_ex.h"
24 #include "securec.h"
25 #include "store_util.h"
26 #include "task_executor.h"
27 namespace OHOS::DistributedKv {
SecurityManager()28 SecurityManager::SecurityManager()
29 {
30 vecRootKeyAlias_ = std::vector<uint8_t>(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS));
31 vecNonce_ = std::vector<uint8_t>(HKS_BLOB_TYPE_NONCE, HKS_BLOB_TYPE_NONCE + strlen(HKS_BLOB_TYPE_NONCE));
32 vecAad_ = std::vector<uint8_t>(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD));
33 }
34
~SecurityManager()35 SecurityManager::~SecurityManager()
36 {}
37
GetInstance()38 SecurityManager &SecurityManager::GetInstance()
39 {
40 static SecurityManager instance;
41 return instance;
42 }
43
Init()44 void SecurityManager::Init()
45 {
46 auto check = Retry();
47 check();
48 }
49
Retry()50 std::function<void()> SecurityManager::Retry()
51 {
52 return [this]() {
53 auto status = CheckRootKey();
54 if (status == HKS_SUCCESS) {
55 ZLOGE("root key already exist.");
56 return;
57 }
58 if (status == HKS_ERROR_NOT_EXIST && GenerateRootKey() == HKS_SUCCESS) {
59 ZLOGE("GenerateRootKey success.");
60 return;
61 }
62 constexpr int32_t interval = 100;
63 TaskExecutor::GetInstance().Execute(Retry(), interval);
64 };
65 }
66
GetDBPassword(const std::string & name,const std::string & path,bool needCreate)67 SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &name,
68 const std::string &path, bool needCreate)
69 {
70 auto secKey = LoadKeyFromFile(name, path);
71 if (secKey.empty()) {
72 if (!needCreate) {
73 return DBPassword();
74 } else {
75 secKey = Random(KEY_SIZE);
76 SaveKeyToFile(name, path, secKey);
77 }
78 }
79 DBPassword password;
80 password.SetValue(secKey.data(), secKey.size());
81 secKey.assign(secKey.size(), 0);
82 return password;
83 }
84
SaveDBPassword(const std::string & name,const std::string & path,const SecurityManager::DBPassword & key)85 bool SecurityManager::SaveDBPassword
86 (const std::string &name, const std::string &path, const SecurityManager::DBPassword &key)
87 {
88 std::vector<uint8_t> pwd(key.GetData(), key.GetData() + key.GetSize());
89 SaveKeyToFile(name, path, pwd);
90 pwd.assign(pwd.size(), 0);
91 return true;
92 }
93
DelDBPassword(const std::string & name,const std::string & path)94 void SecurityManager::DelDBPassword(const std::string &name, const std::string &path)
95 {
96 auto keyPath = path + "/key/" + name + ".key";
97 StoreUtil::Remove(keyPath);
98 }
99
Random(int32_t len)100 std::vector<uint8_t> SecurityManager::Random(int32_t len)
101 {
102 std::random_device randomDevice;
103 std::uniform_int_distribution<int> distribution(0, std::numeric_limits<uint8_t>::max());
104 std::vector<uint8_t> key(len);
105 for (int32_t i = 0; i < len; i++) {
106 key[i] = static_cast<uint8_t>(distribution(randomDevice));
107 }
108 return key;
109 }
110
LoadKeyFromFile(const std::string & name,const std::string & path)111 std::vector<uint8_t> SecurityManager::LoadKeyFromFile(const std::string &name, const std::string &path)
112 {
113 auto keyPath = path + "/key/" + name + ".key";
114 if (!FileExists(keyPath)) {
115 return {};
116 }
117
118 std::vector<char> content;
119 auto loaded = LoadBufferFromFile(keyPath, content);
120 if (!loaded) {
121 return {};
122 }
123
124 if (content.size() < (sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE + 1) {
125 return {};
126 }
127
128 size_t offset = 0;
129 if (content[offset] != char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)) {
130 return {};
131 }
132
133 offset++;
134 std::vector<uint8_t> date;
135 date.assign(content.begin() + offset, content.begin() + (sizeof(time_t) / sizeof(uint8_t)) + offset);
136 offset += (sizeof(time_t) / sizeof(uint8_t));
137 std::vector<uint8_t> key{content.begin() + offset, content.end()};
138
139 std::vector<uint8_t> secretKey {};
140 content.assign(content.size(), 0);
141 if(!Decrypt(key, secretKey)) {
142 ZLOGE("client Decrypt failed");
143 return {};
144 }
145 return secretKey;
146 }
147
SaveKeyToFile(const std::string & name,const std::string & path,std::vector<uint8_t> & key)148 bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string &path, std::vector<uint8_t> &key)
149 {
150 if (CheckRootKey() != HKS_SUCCESS) {
151 ZLOGE("client rootkey generation failed");
152 return false;
153 }
154
155 auto secretKey = Encrypt(key);
156 auto keyPath = path + "/key";
157 StoreUtil::InitPath(keyPath);
158 std::vector<char> content;
159 auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now());
160 std::vector<uint8_t> date(reinterpret_cast<uint8_t *>(&time), reinterpret_cast<uint8_t *>(&time) + sizeof(time));
161 content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE));
162 content.insert(content.end(), date.begin(), date.end());
163 content.insert(content.end(), secretKey.begin(), secretKey.end());
164 auto keyFullPath = keyPath+ "/" + name + ".key";
165 auto ret = SaveBufferToFile(keyFullPath, content);
166 content.assign(content.size(), 0);
167 if (!ret) {
168 ZLOGE("client SaveSecretKey failed!");
169 return false;
170 }
171 return ret;
172 }
173
Encrypt(const std::vector<uint8_t> & key)174 std::vector<uint8_t> SecurityManager::Encrypt(const std::vector<uint8_t> &key)
175 {
176 struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() };
177 struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), vecNonce_.data() };
178 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
179 struct HksBlob plainKey = { uint32_t(key.size()), const_cast<uint8_t *>(key.data()) };
180 struct HksParamSet *params = nullptr;
181 int32_t ret = HksInitParamSet(¶ms);
182 if (ret != HKS_SUCCESS) {
183 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
184 return {};
185 }
186 struct HksParam hksParam[] = {
187 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
188 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
189 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
190 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
191 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
192 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
193 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
194 };
195 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
196 if (ret != HKS_SUCCESS) {
197 ZLOGE("HksAddParams failed, status: %{public}d", ret);
198 HksFreeParamSet(¶ms);
199 return {};
200 }
201
202 ret = HksBuildParamSet(¶ms);
203 if (ret != HKS_SUCCESS) {
204 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
205 HksFreeParamSet(¶ms);
206 return {};
207 }
208
209 uint8_t cipherBuf[256] = { 0 };
210 struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf };
211 ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText);
212 (void)HksFreeParamSet(¶ms);
213 if (ret != HKS_SUCCESS) {
214 ZLOGE("HksEncrypt failed, status: %{public}d", ret);
215 return {};
216 }
217 std::vector<uint8_t> encryptedKey(cipherText.data, cipherText.data + cipherText.size);
218 (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf));
219 return encryptedKey;
220 }
221
Decrypt(std::vector<uint8_t> & source,std::vector<uint8_t> & key)222 bool SecurityManager::Decrypt(std::vector<uint8_t> &source, std::vector<uint8_t> &key)
223 {
224 struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) };
225 struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), &(vecNonce_[0]) };
226 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) };
227 struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() };
228
229 struct HksParamSet *params = nullptr;
230 int32_t ret = HksInitParamSet(¶ms);
231 if (ret != HKS_SUCCESS) {
232 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
233 return false;
234 }
235 struct HksParam hksParam[] = {
236 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
237 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
238 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
239 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
240 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
241 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
242 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
243 };
244 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
245 if (ret != HKS_SUCCESS) {
246 ZLOGE("HksAddParams failed, status: %{public}d", ret);
247 HksFreeParamSet(¶ms);
248 return false;
249 }
250
251 ret = HksBuildParamSet(¶ms);
252 if (ret != HKS_SUCCESS) {
253 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
254 HksFreeParamSet(¶ms);
255 return false;
256 }
257
258 uint8_t plainBuf[256] = { 0 };
259 struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf };
260 ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob);
261 (void)HksFreeParamSet(¶ms);
262 if (ret != HKS_SUCCESS) {
263 ZLOGE("HksDecrypt, status: %{public}d", ret);
264 return false;
265 }
266
267 key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size);
268 (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf));
269 return true;
270 }
271
GenerateRootKey()272 int32_t SecurityManager::GenerateRootKey()
273 {
274 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
275 struct HksParamSet *params = nullptr;
276 int32_t ret = HksInitParamSet(¶ms);
277 if (ret != HKS_SUCCESS) {
278 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
279 return ret;
280 }
281
282 struct HksParam hksParam[] = {
283 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
284 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
285 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
286 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
287 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
288 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
289 };
290
291 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
292 if (ret != HKS_SUCCESS) {
293 ZLOGE("HksAddParams failed, status: %{public}d", ret);
294 HksFreeParamSet(¶ms);
295 return ret;
296 }
297
298 ret = HksBuildParamSet(¶ms);
299 if (ret != HKS_SUCCESS) {
300 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
301 HksFreeParamSet(¶ms);
302 return ret;
303 }
304
305 ret = HksGenerateKey(&rootKeyName, params, nullptr);
306 HksFreeParamSet(¶ms);
307 ZLOGI("HksGenerateKey status: %{public}d", ret);
308 return ret;
309 }
310
CheckRootKey()311 int32_t SecurityManager::CheckRootKey()
312 {
313 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
314 struct HksParamSet *params = nullptr;
315 int32_t ret = HksInitParamSet(¶ms);
316 if (ret != HKS_SUCCESS) {
317 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
318 return ret;
319 }
320
321 struct HksParam hksParam[] = {
322 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
323 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
324 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
325 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
326 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
327 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
328 };
329
330 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
331 if (ret != HKS_SUCCESS) {
332 ZLOGE("HksAddParams failed, status: %{public}d", ret);
333 HksFreeParamSet(¶ms);
334 return ret;
335 }
336
337 ret = HksBuildParamSet(¶ms);
338 if (ret != HKS_SUCCESS) {
339 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
340 HksFreeParamSet(¶ms);
341 return ret;
342 }
343
344 ret = HksKeyExist(&rootKeyName, params);
345 HksFreeParamSet(¶ms);
346 ZLOGI("HksKeyExist status: %{public}d", ret);
347 return ret;
348 }
349 } // namespace OHOS::DistributedKv