• 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 <limits>
20 #include <random>
21 #include <unistd.h>
22 
23 #include "file_ex.h"
24 #include "hks_api.h"
25 #include "hks_param.h"
26 #include "log_print.h"
27 #include "securec.h"
28 #include "store_types.h"
29 #include "store_util.h"
30 #include "task_executor.h"
31 namespace OHOS::DistributedKv {
SecurityManager()32 SecurityManager::SecurityManager()
33 {
34     vecRootKeyAlias_ = std::vector<uint8_t>(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS));
35     vecNonce_ = std::vector<uint8_t>(HKS_BLOB_TYPE_NONCE, HKS_BLOB_TYPE_NONCE + strlen(HKS_BLOB_TYPE_NONCE));
36     vecAad_ = std::vector<uint8_t>(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD));
37 }
38 
~SecurityManager()39 SecurityManager::~SecurityManager()
40 {}
41 
GetInstance()42 SecurityManager &SecurityManager::GetInstance()
43 {
44     static SecurityManager instance;
45     return instance;
46 }
47 
Retry()48 bool SecurityManager::Retry()
49 {
50     auto status = CheckRootKey();
51     if (status == HKS_SUCCESS) {
52         hasRootKey_ = true;
53         ZLOGE("root key already exist.");
54         return true;
55     }
56 
57     if (status == HKS_ERROR_NOT_EXIST && GenerateRootKey() == HKS_SUCCESS) {
58         hasRootKey_ = true;
59         ZLOGE("GenerateRootKey success.");
60         return true;
61     }
62 
63     constexpr int32_t interval = 100;
64     TaskExecutor::GetInstance().Schedule(std::chrono::milliseconds(interval), [this] {
65         Retry();
66     });
67     return false;
68 }
69 
GetDBPassword(const std::string & name,const std::string & path,bool needCreate)70 SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &name,
71     const std::string &path, bool needCreate)
72 {
73     DBPassword dbPassword;
74     auto secKey = LoadKeyFromFile(name, path, dbPassword.isKeyOutdated);
75     std::vector<uint8_t> key{};
76 
77     if (secKey.empty() && needCreate) {
78         key = Random(KEY_SIZE);
79         if (!SaveKeyToFile(name, path, key)) {
80             secKey.assign(secKey.size(), 0);
81             key.assign(key.size(), 0);
82             return dbPassword;
83         }
84     }
85 
86     if ((!secKey.empty() && Decrypt(secKey, key)) || !key.empty()) {
87         dbPassword.SetValue(key.data(), key.size());
88     }
89 
90     secKey.assign(secKey.size(), 0);
91     key.assign(key.size(), 0);
92     return dbPassword;
93 }
94 
SaveDBPassword(const std::string & name,const std::string & path,const DistributedDB::CipherPassword & key)95 bool SecurityManager::SaveDBPassword(const std::string &name, const std::string &path,
96     const DistributedDB::CipherPassword &key)
97 {
98     std::vector<uint8_t> pwd(key.GetData(), key.GetData() + key.GetSize());
99     auto result = SaveKeyToFile(name, path, pwd);
100     pwd.assign(pwd.size(), 0);
101     return result;
102 }
103 
DelDBPassword(const std::string & name,const std::string & path)104 void SecurityManager::DelDBPassword(const std::string &name, const std::string &path)
105 {
106     auto keyPath = path + "/key/" + name + ".key";
107     StoreUtil::Remove(keyPath);
108 }
109 
Random(int32_t len)110 std::vector<uint8_t> SecurityManager::Random(int32_t len)
111 {
112     std::random_device randomDevice;
113     std::uniform_int_distribution<int> distribution(0, std::numeric_limits<uint8_t>::max());
114     std::vector<uint8_t> key(len);
115     for (int32_t i = 0; i < len; i++) {
116         key[i] = static_cast<uint8_t>(distribution(randomDevice));
117     }
118     return key;
119 }
120 
LoadKeyFromFile(const std::string & name,const std::string & path,bool & isOutdated)121 std::vector<uint8_t> SecurityManager::LoadKeyFromFile(const std::string &name, const std::string &path,
122     bool &isOutdated)
123 {
124     auto keyPath = path + "/key/" + name + ".key";
125     if (!FileExists(keyPath)) {
126         return {};
127     }
128 
129     std::vector<char> content;
130     auto loaded = LoadBufferFromFile(keyPath, content);
131     if (!loaded) {
132         return {};
133     }
134 
135     if (content.size() < (sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE + 1) {
136         return {};
137     }
138 
139     size_t offset = 0;
140     if (content[offset] != char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)) {
141         return {};
142     }
143 
144     offset++;
145     std::vector<uint8_t> date;
146     date.assign(content.begin() + offset, content.begin() + (sizeof(time_t) / sizeof(uint8_t)) + offset);
147     isOutdated = IsKeyOutdated(date);
148     offset += (sizeof(time_t) / sizeof(uint8_t));
149     std::vector<uint8_t> key{ content.begin() + offset, content.end() };
150     content.assign(content.size(), 0);
151     return key;
152 }
153 
SaveKeyToFile(const std::string & name,const std::string & path,std::vector<uint8_t> & key)154 bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string &path, std::vector<uint8_t> &key)
155 {
156     if (!hasRootKey_ && !Retry()) {
157         ZLOGE("failed! no root key and generation failed");
158         return false;
159     }
160     auto secretKey = Encrypt(key);
161     auto keyPath = path + "/key";
162     StoreUtil::InitPath(keyPath);
163     std::vector<char> content;
164     auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now());
165     std::vector<uint8_t> date(reinterpret_cast<uint8_t *>(&time), reinterpret_cast<uint8_t *>(&time) + sizeof(time));
166     content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE));
167     content.insert(content.end(), date.begin(), date.end());
168     content.insert(content.end(), secretKey.begin(), secretKey.end());
169     auto keyFullPath = keyPath + "/" + name + ".key";
170     auto ret = SaveBufferToFile(keyFullPath, content);
171     content.assign(content.size(), 0);
172     if (!ret) {
173         ZLOGE("client SaveSecretKey failed!");
174         return false;
175     }
176     return ret;
177 }
178 
Encrypt(const std::vector<uint8_t> & key)179 std::vector<uint8_t> SecurityManager::Encrypt(const std::vector<uint8_t> &key)
180 {
181     struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() };
182     struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), vecNonce_.data() };
183     struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
184     struct HksBlob plainKey = { uint32_t(key.size()), const_cast<uint8_t *>(key.data()) };
185     struct HksParamSet *params = nullptr;
186     int32_t ret = HksInitParamSet(&params);
187     if (ret != HKS_SUCCESS) {
188         ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
189         return {};
190     }
191     struct HksParam hksParam[] = {
192         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
193         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
194         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
195         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
196         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
197         { .tag = HKS_TAG_NONCE, .blob = blobNonce },
198         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
199     };
200     ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
201     if (ret != HKS_SUCCESS) {
202         ZLOGE("HksAddParams failed, status: %{public}d", ret);
203         HksFreeParamSet(&params);
204         return {};
205     }
206 
207     ret = HksBuildParamSet(&params);
208     if (ret != HKS_SUCCESS) {
209         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
210         HksFreeParamSet(&params);
211         return {};
212     }
213 
214     uint8_t cipherBuf[256] = { 0 };
215     struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf };
216     ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText);
217     (void)HksFreeParamSet(&params);
218     if (ret != HKS_SUCCESS) {
219         ZLOGE("HksEncrypt failed, status: %{public}d", ret);
220         return {};
221     }
222     std::vector<uint8_t> encryptedKey(cipherText.data, cipherText.data + cipherText.size);
223     (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf));
224     return encryptedKey;
225 }
226 
Decrypt(std::vector<uint8_t> & source,std::vector<uint8_t> & key)227 bool SecurityManager::Decrypt(std::vector<uint8_t> &source, std::vector<uint8_t> &key)
228 {
229     struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) };
230     struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), &(vecNonce_[0]) };
231     struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) };
232     struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() };
233 
234     struct HksParamSet *params = nullptr;
235     int32_t ret = HksInitParamSet(&params);
236     if (ret != HKS_SUCCESS) {
237         ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
238         return false;
239     }
240     struct HksParam hksParam[] = {
241         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
242         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
243         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
244         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
245         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
246         { .tag = HKS_TAG_NONCE, .blob = blobNonce },
247         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
248     };
249     ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
250     if (ret != HKS_SUCCESS) {
251         ZLOGE("HksAddParams failed, status: %{public}d", ret);
252         HksFreeParamSet(&params);
253         return false;
254     }
255 
256     ret = HksBuildParamSet(&params);
257     if (ret != HKS_SUCCESS) {
258         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
259         HksFreeParamSet(&params);
260         return false;
261     }
262 
263     uint8_t plainBuf[256] = { 0 };
264     struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf };
265     ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob);
266     (void)HksFreeParamSet(&params);
267     if (ret != HKS_SUCCESS) {
268         ZLOGE("HksDecrypt, status: %{public}d", ret);
269         return false;
270     }
271 
272     key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size);
273     (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf));
274     return true;
275 }
276 
GenerateRootKey()277 int32_t SecurityManager::GenerateRootKey()
278 {
279     struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
280     struct HksParamSet *params = nullptr;
281     int32_t ret = HksInitParamSet(&params);
282     if (ret != HKS_SUCCESS) {
283         ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
284         return ret;
285     }
286 
287     struct HksParam hksParam[] = {
288         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
289         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
290         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
291         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
292         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
293         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
294     };
295 
296     ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
297     if (ret != HKS_SUCCESS) {
298         ZLOGE("HksAddParams failed, status: %{public}d", ret);
299         HksFreeParamSet(&params);
300         return ret;
301     }
302 
303     ret = HksBuildParamSet(&params);
304     if (ret != HKS_SUCCESS) {
305         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
306         HksFreeParamSet(&params);
307         return ret;
308     }
309 
310     ret = HksGenerateKey(&rootKeyName, params, nullptr);
311     HksFreeParamSet(&params);
312     ZLOGI("HksGenerateKey status: %{public}d", ret);
313     return ret;
314 }
315 
CheckRootKey()316 int32_t SecurityManager::CheckRootKey()
317 {
318     struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
319     struct HksParamSet *params = nullptr;
320     int32_t ret = HksInitParamSet(&params);
321     if (ret != HKS_SUCCESS) {
322         ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
323         return ret;
324     }
325 
326     struct HksParam hksParam[] = {
327         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
328         { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
329         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
330         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
331         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
332         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
333     };
334 
335     ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
336     if (ret != HKS_SUCCESS) {
337         ZLOGE("HksAddParams failed, status: %{public}d", ret);
338         HksFreeParamSet(&params);
339         return ret;
340     }
341 
342     ret = HksBuildParamSet(&params);
343     if (ret != HKS_SUCCESS) {
344         ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
345         HksFreeParamSet(&params);
346         return ret;
347     }
348 
349     ret = HksKeyExist(&rootKeyName, params);
350     HksFreeParamSet(&params);
351     ZLOGI("HksKeyExist status: %{public}d", ret);
352     return ret;
353 }
354 
IsKeyOutdated(const std::vector<uint8_t> & date)355 bool SecurityManager::IsKeyOutdated(const std::vector<uint8_t> &date)
356 {
357     time_t time = *reinterpret_cast<time_t *>(const_cast<uint8_t *>(&date[0]));
358     auto createTime = std::chrono::system_clock::from_time_t(time);
359     return ((createTime + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now());
360 }
361 
362 } // namespace OHOS::DistributedKv
363