• 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 #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(&params);
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(&params);
199         return {};
200     }
201 
202     ret = HksBuildParamSet(&params);
203     if (ret != HKS_SUCCESS) {
204         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
205         HksFreeParamSet(&params);
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(&params);
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(&params);
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(&params);
248         return false;
249     }
250 
251     ret = HksBuildParamSet(&params);
252     if (ret != HKS_SUCCESS) {
253         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
254         HksFreeParamSet(&params);
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(&params);
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(&params);
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(&params);
295         return ret;
296     }
297 
298     ret = HksBuildParamSet(&params);
299     if (ret != HKS_SUCCESS) {
300         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
301         HksFreeParamSet(&params);
302         return ret;
303     }
304 
305     ret = HksGenerateKey(&rootKeyName, params, nullptr);
306     HksFreeParamSet(&params);
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(&params);
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(&params);
334         return ret;
335     }
336 
337     ret = HksBuildParamSet(&params);
338     if (ret != HKS_SUCCESS) {
339         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
340         HksFreeParamSet(&params);
341         return ret;
342     }
343 
344     ret = HksKeyExist(&rootKeyName, params);
345     HksFreeParamSet(&params);
346     ZLOGI("HksKeyExist status: %{public}d", ret);
347     return ret;
348 }
349 } // namespace OHOS::DistributedKv