• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params);
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(&params);
222         return {};
223     }
224 
225     ret = HksBuildParamSet(&params);
226     if (ret != HKS_SUCCESS) {
227         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
228         HksFreeParamSet(&params);
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(&params);
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(&params);
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(&params);
272         return false;
273     }
274 
275     ret = HksBuildParamSet(&params);
276     if (ret != HKS_SUCCESS) {
277         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
278         HksFreeParamSet(&params);
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(&params);
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(&params);
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(&params);
320         return ret;
321     }
322 
323     ret = HksBuildParamSet(&params);
324     if (ret != HKS_SUCCESS) {
325         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
326         HksFreeParamSet(&params);
327         return ret;
328     }
329 
330     ret = HksGenerateKey(&rootKeyName, params, nullptr);
331     HksFreeParamSet(&params);
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(&params);
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(&params);
360         return ret;
361     }
362 
363     ret = HksBuildParamSet(&params);
364     if (ret != HKS_SUCCESS) {
365         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
366         HksFreeParamSet(&params);
367         return ret;
368     }
369 
370     ret = HksKeyExist(&rootKeyName, params);
371     HksFreeParamSet(&params);
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