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
18 #include <chrono>
19 #include <fcntl.h>
20 #include <limits>
21 #include <random>
22 #include <sys/file.h>
23 #include <unistd.h>
24
25 #include "file_ex.h"
26 #include "hks_api.h"
27 #include "hks_param.h"
28 #include "log_print.h"
29 #include "securec.h"
30 #include "store_types.h"
31 #include "store_util.h"
32 #include "task_executor.h"
33 namespace OHOS::DistributedKv {
SecurityManager()34 SecurityManager::SecurityManager()
35 {
36 vecRootKeyAlias_ = std::vector<uint8_t>(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS));
37 vecNonce_ = std::vector<uint8_t>(HKS_BLOB_TYPE_NONCE, HKS_BLOB_TYPE_NONCE + strlen(HKS_BLOB_TYPE_NONCE));
38 vecAad_ = std::vector<uint8_t>(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD));
39 }
40
~SecurityManager()41 SecurityManager::~SecurityManager()
42 {}
43
GetInstance()44 SecurityManager &SecurityManager::GetInstance()
45 {
46 static SecurityManager instance;
47 return instance;
48 }
49
Retry()50 bool SecurityManager::Retry()
51 {
52 auto status = CheckRootKey();
53 if (status == HKS_SUCCESS) {
54 hasRootKey_ = true;
55 ZLOGE("Root key already exist.");
56 return true;
57 }
58
59 if (status == HKS_ERROR_NOT_EXIST && GenerateRootKey() == HKS_SUCCESS) {
60 hasRootKey_ = true;
61 ZLOGE("GenerateRootKey success.");
62 return true;
63 }
64
65 constexpr int32_t interval = 100;
66 TaskExecutor::GetInstance().Schedule(std::chrono::milliseconds(interval), [this] {
67 Retry();
68 });
69 return false;
70 }
71
GetDBPassword(const std::string & name,const std::string & path,bool needCreate)72 SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &name,
73 const std::string &path, bool needCreate)
74 {
75 DBPassword dbPassword;
76 KeyFiles keyFiles(name, path);
77 KeyFilesAutoLock fileLock(keyFiles);
78 auto secKey = LoadKeyFromFile(name, path, dbPassword.isKeyOutdated);
79 std::vector<uint8_t> key{};
80
81 if (secKey.empty() && needCreate) {
82 key = Random(KEY_SIZE);
83 if (!SaveKeyToFile(name, path, key)) {
84 secKey.assign(secKey.size(), 0);
85 key.assign(key.size(), 0);
86 return dbPassword;
87 }
88 }
89
90 if ((!secKey.empty() && Decrypt(secKey, key)) || !key.empty()) {
91 dbPassword.SetValue(key.data(), key.size());
92 }
93
94 secKey.assign(secKey.size(), 0);
95 key.assign(key.size(), 0);
96 return dbPassword;
97 }
98
SaveDBPassword(const std::string & name,const std::string & path,const DistributedDB::CipherPassword & key)99 bool SecurityManager::SaveDBPassword(const std::string &name, const std::string &path,
100 const DistributedDB::CipherPassword &key)
101 {
102 KeyFiles keyFiles(name, path);
103 KeyFilesAutoLock fileLock(keyFiles);
104 std::vector<uint8_t> pwd(key.GetData(), key.GetData() + key.GetSize());
105 auto result = SaveKeyToFile(name, path, pwd);
106 pwd.assign(pwd.size(), 0);
107 return result;
108 }
109
DelDBPassword(const std::string & name,const std::string & path)110 void SecurityManager::DelDBPassword(const std::string &name, const std::string &path)
111 {
112 KeyFiles keyFiles(name, path);
113 KeyFilesAutoLock fileLock(keyFiles);
114 auto keyPath = keyFiles.GetKeyFilePath();
115 StoreUtil::Remove(keyPath);
116 fileLock.UnLockAndDestroy();
117 }
118
Random(int32_t len)119 std::vector<uint8_t> SecurityManager::Random(int32_t len)
120 {
121 std::random_device randomDevice;
122 std::uniform_int_distribution<int> distribution(0, std::numeric_limits<uint8_t>::max());
123 std::vector<uint8_t> key(len);
124 for (int32_t i = 0; i < len; i++) {
125 key[i] = static_cast<uint8_t>(distribution(randomDevice));
126 }
127 return key;
128 }
129
LoadKeyFromFile(const std::string & name,const std::string & path,bool & isOutdated)130 std::vector<uint8_t> SecurityManager::LoadKeyFromFile(const std::string &name, const std::string &path,
131 bool &isOutdated)
132 {
133 auto keyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY;
134 if (!FileExists(keyPath)) {
135 return {};
136 }
137 StoreUtil::RemoveRWXForOthers(path + KEY_DIR);
138
139 std::vector<char> content;
140 auto loaded = LoadBufferFromFile(keyPath, content);
141 if (!loaded) {
142 return {};
143 }
144
145 if (content.size() < (sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE + 1) {
146 return {};
147 }
148
149 size_t offset = 0;
150 if (content[offset] != char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)) {
151 return {};
152 }
153
154 offset++;
155 std::vector<uint8_t> date;
156 date.assign(content.begin() + offset, content.begin() + (sizeof(time_t) / sizeof(uint8_t)) + offset);
157 isOutdated = IsKeyOutdated(date);
158 offset += (sizeof(time_t) / sizeof(uint8_t));
159 std::vector<uint8_t> key{ content.begin() + offset, content.end() };
160 content.assign(content.size(), 0);
161 return key;
162 }
163
SaveKeyToFile(const std::string & name,const std::string & path,std::vector<uint8_t> & key)164 bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string &path, std::vector<uint8_t> &key)
165 {
166 if (!hasRootKey_ && !Retry()) {
167 ZLOGE("Failed! no root key and generation failed");
168 return false;
169 }
170 auto secretKey = Encrypt(key);
171 if (secretKey.empty()) {
172 ZLOGE("Failed! encrypt failed");
173 return false;
174 }
175 auto keyPath = path + KEY_DIR;
176 StoreUtil::InitPath(keyPath);
177 std::vector<char> content;
178 auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now());
179 std::vector<uint8_t> date(reinterpret_cast<uint8_t *>(&time), reinterpret_cast<uint8_t *>(&time) + sizeof(time));
180 content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE));
181 content.insert(content.end(), date.begin(), date.end());
182 content.insert(content.end(), secretKey.begin(), secretKey.end());
183 auto keyFullPath = keyPath + SLASH + name + SUFFIX_KEY;
184 auto ret = SaveBufferToFile(keyFullPath, content);
185 if (access(keyFullPath.c_str(), F_OK) == 0) {
186 StoreUtil::RemoveRWXForOthers(keyFullPath);
187 }
188 content.assign(content.size(), 0);
189 if (!ret) {
190 ZLOGE("Client SaveSecretKey failed!");
191 return false;
192 }
193 return ret;
194 }
195
Encrypt(const std::vector<uint8_t> & key)196 std::vector<uint8_t> SecurityManager::Encrypt(const std::vector<uint8_t> &key)
197 {
198 struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() };
199 struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), vecNonce_.data() };
200 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
201 struct HksBlob plainKey = { uint32_t(key.size()), const_cast<uint8_t *>(key.data()) };
202 struct HksParamSet *params = nullptr;
203 int32_t ret = HksInitParamSet(¶ms);
204 if (ret != HKS_SUCCESS) {
205 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
206 return {};
207 }
208 struct HksParam hksParam[] = {
209 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
210 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
211 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
212 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
213 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
214 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
215 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
216 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
217 };
218 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
219 if (ret != HKS_SUCCESS) {
220 ZLOGE("HksAddParams failed, status: %{public}d", ret);
221 HksFreeParamSet(¶ms);
222 return {};
223 }
224
225 ret = HksBuildParamSet(¶ms);
226 if (ret != HKS_SUCCESS) {
227 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
228 HksFreeParamSet(¶ms);
229 return {};
230 }
231
232 uint8_t cipherBuf[256] = { 0 };
233 struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf };
234 ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText);
235 (void)HksFreeParamSet(¶ms);
236 if (ret != HKS_SUCCESS) {
237 ZLOGE("HksEncrypt failed, status: %{public}d", ret);
238 return {};
239 }
240 std::vector<uint8_t> encryptedKey(cipherText.data, cipherText.data + cipherText.size);
241 (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf));
242 return encryptedKey;
243 }
244
Decrypt(std::vector<uint8_t> & source,std::vector<uint8_t> & key)245 bool SecurityManager::Decrypt(std::vector<uint8_t> &source, std::vector<uint8_t> &key)
246 {
247 struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) };
248 struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), &(vecNonce_[0]) };
249 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) };
250 struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() };
251
252 struct HksParamSet *params = nullptr;
253 int32_t ret = HksInitParamSet(¶ms);
254 if (ret != HKS_SUCCESS) {
255 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
256 return false;
257 }
258 struct HksParam hksParam[] = {
259 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
260 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
261 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
262 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
263 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
264 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
265 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
266 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
267 };
268 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
269 if (ret != HKS_SUCCESS) {
270 ZLOGE("HksAddParams failed, status: %{public}d", ret);
271 HksFreeParamSet(¶ms);
272 return false;
273 }
274
275 ret = HksBuildParamSet(¶ms);
276 if (ret != HKS_SUCCESS) {
277 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
278 HksFreeParamSet(¶ms);
279 return false;
280 }
281
282 uint8_t plainBuf[256] = { 0 };
283 struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf };
284 ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob);
285 (void)HksFreeParamSet(¶ms);
286 if (ret != HKS_SUCCESS) {
287 ZLOGE("HksDecrypt, status: %{public}d", ret);
288 return false;
289 }
290
291 key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size);
292 (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf));
293 return true;
294 }
295
GenerateRootKey()296 int32_t SecurityManager::GenerateRootKey()
297 {
298 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
299 struct HksParamSet *params = nullptr;
300 int32_t ret = HksInitParamSet(¶ms);
301 if (ret != HKS_SUCCESS) {
302 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
303 return ret;
304 }
305
306 struct HksParam hksParam[] = {
307 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
308 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
309 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
310 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
311 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
312 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
313 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
314 };
315
316 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
317 if (ret != HKS_SUCCESS) {
318 ZLOGE("HksAddParams failed, status: %{public}d", ret);
319 HksFreeParamSet(¶ms);
320 return ret;
321 }
322
323 ret = HksBuildParamSet(¶ms);
324 if (ret != HKS_SUCCESS) {
325 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
326 HksFreeParamSet(¶ms);
327 return ret;
328 }
329
330 ret = HksGenerateKey(&rootKeyName, params, nullptr);
331 HksFreeParamSet(¶ms);
332 ZLOGI("HksGenerateKey status: %{public}d", ret);
333 return ret;
334 }
335
CheckRootKey()336 int32_t SecurityManager::CheckRootKey()
337 {
338 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
339 struct HksParamSet *params = nullptr;
340 int32_t ret = HksInitParamSet(¶ms);
341 if (ret != HKS_SUCCESS) {
342 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
343 return ret;
344 }
345
346 struct HksParam hksParam[] = {
347 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
348 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
349 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
350 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
351 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
352 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
353 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
354 };
355
356 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
357 if (ret != HKS_SUCCESS) {
358 ZLOGE("HksAddParams failed, status: %{public}d", ret);
359 HksFreeParamSet(¶ms);
360 return ret;
361 }
362
363 ret = HksBuildParamSet(¶ms);
364 if (ret != HKS_SUCCESS) {
365 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
366 HksFreeParamSet(¶ms);
367 return ret;
368 }
369
370 ret = HksKeyExist(&rootKeyName, params);
371 HksFreeParamSet(¶ms);
372 ZLOGI("HksKeyExist status: %{public}d", ret);
373 return ret;
374 }
375
IsKeyOutdated(const std::vector<uint8_t> & date)376 bool SecurityManager::IsKeyOutdated(const std::vector<uint8_t> &date)
377 {
378 time_t time = *reinterpret_cast<time_t *>(const_cast<uint8_t *>(&date[0]));
379 auto createTime = std::chrono::system_clock::from_time_t(time);
380 return ((createTime + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now());
381 }
382
KeyFiles(const std::string & name,const std::string & path,bool openFile)383 SecurityManager::KeyFiles::KeyFiles(const std::string &name, const std::string &path, bool openFile)
384 {
385 keyPath_ = path + KEY_DIR + SLASH + name + SUFFIX_KEY;
386 lockFile_ = path + KEY_DIR + SLASH + name + SUFFIX_KEY_LOCK;
387 StoreUtil::InitPath(path + KEY_DIR);
388 if (!openFile) {
389 return;
390 }
391 lockFd_ = open(lockFile_.c_str(), O_RDONLY | O_CREAT, S_IRWXU | S_IRWXG);
392 if (lockFd_ < 0) {
393 ZLOGE("Open failed, errno:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(lockFile_).c_str());
394 }
395 }
396
~KeyFiles()397 SecurityManager::KeyFiles::~KeyFiles()
398 {
399 if (lockFd_ < 0) {
400 return;
401 }
402 close(lockFd_);
403 lockFd_ = -1;
404 }
405
GetKeyFilePath()406 const std::string &SecurityManager::KeyFiles::GetKeyFilePath()
407 {
408 return keyPath_;
409 }
410
Lock()411 int32_t SecurityManager::KeyFiles::Lock()
412 {
413 return FileLock(LOCK_EX);
414 }
415
UnLock()416 int32_t SecurityManager::KeyFiles::UnLock()
417 {
418 return FileLock(LOCK_UN);
419 }
420
DestroyLock()421 int32_t SecurityManager::KeyFiles::DestroyLock()
422 {
423 if (lockFd_ > 0) {
424 close(lockFd_);
425 lockFd_ = -1;
426 }
427 StoreUtil::Remove(lockFile_);
428 return Status::SUCCESS;
429 }
430
FileLock(int32_t lockType)431 int32_t SecurityManager::KeyFiles::FileLock(int32_t lockType)
432 {
433 if (lockFd_ < 0) {
434 return Status::INVALID_ARGUMENT;
435 }
436 int32_t errCode = 0;
437 do {
438 errCode = flock(lockFd_, lockType);
439 } while (errCode < 0 && errno == EINTR);
440 if (errCode < 0) {
441 ZLOGE("This flock is failed, type:%{public}d, errno:%{public}d, path:%{public}s", lockType, errno,
442 StoreUtil::Anonymous(lockFile_).c_str());
443 return Status::ERROR;
444 }
445 return Status::SUCCESS;
446 }
447
KeyFilesAutoLock(KeyFiles & keyFiles)448 SecurityManager::KeyFilesAutoLock::KeyFilesAutoLock(KeyFiles& keyFiles) : keyFiles_(keyFiles)
449 {
450 keyFiles_.Lock();
451 }
452
~KeyFilesAutoLock()453 SecurityManager::KeyFilesAutoLock::~KeyFilesAutoLock()
454 {
455 keyFiles_.UnLock();
456 }
UnLockAndDestroy()457 int32_t SecurityManager::KeyFilesAutoLock::UnLockAndDestroy()
458 {
459 keyFiles_.UnLock();
460 return keyFiles_.DestroyLock();
461 }
462 } // namespace OHOS::DistributedKv
463