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 StoreUtil::RemoveRWXForOthers(path + "/key");
129
130 std::vector<char> content;
131 auto loaded = LoadBufferFromFile(keyPath, content);
132 if (!loaded) {
133 return {};
134 }
135
136 if (content.size() < (sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE + 1) {
137 return {};
138 }
139
140 size_t offset = 0;
141 if (content[offset] != char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)) {
142 return {};
143 }
144
145 offset++;
146 std::vector<uint8_t> date;
147 date.assign(content.begin() + offset, content.begin() + (sizeof(time_t) / sizeof(uint8_t)) + offset);
148 isOutdated = IsKeyOutdated(date);
149 offset += (sizeof(time_t) / sizeof(uint8_t));
150 std::vector<uint8_t> key{ content.begin() + offset, content.end() };
151 content.assign(content.size(), 0);
152 return key;
153 }
154
SaveKeyToFile(const std::string & name,const std::string & path,std::vector<uint8_t> & key)155 bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string &path, std::vector<uint8_t> &key)
156 {
157 if (!hasRootKey_ && !Retry()) {
158 ZLOGE("failed! no root key and generation failed");
159 return false;
160 }
161 auto secretKey = Encrypt(key);
162 auto keyPath = path + "/key";
163 StoreUtil::InitPath(keyPath);
164 std::vector<char> content;
165 auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now());
166 std::vector<uint8_t> date(reinterpret_cast<uint8_t *>(&time), reinterpret_cast<uint8_t *>(&time) + sizeof(time));
167 content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE));
168 content.insert(content.end(), date.begin(), date.end());
169 content.insert(content.end(), secretKey.begin(), secretKey.end());
170 auto keyFullPath = keyPath + "/" + name + ".key";
171 auto ret = SaveBufferToFile(keyFullPath, content);
172 if (access(keyFullPath.c_str(), F_OK) == 0) {
173 StoreUtil::RemoveRWXForOthers(keyFullPath);
174 }
175 content.assign(content.size(), 0);
176 if (!ret) {
177 ZLOGE("client SaveSecretKey failed!");
178 return false;
179 }
180 return ret;
181 }
182
Encrypt(const std::vector<uint8_t> & key)183 std::vector<uint8_t> SecurityManager::Encrypt(const std::vector<uint8_t> &key)
184 {
185 struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() };
186 struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), vecNonce_.data() };
187 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
188 struct HksBlob plainKey = { uint32_t(key.size()), const_cast<uint8_t *>(key.data()) };
189 struct HksParamSet *params = nullptr;
190 int32_t ret = HksInitParamSet(¶ms);
191 if (ret != HKS_SUCCESS) {
192 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
193 return {};
194 }
195 struct HksParam hksParam[] = {
196 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
197 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
198 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
199 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
200 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
201 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
202 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
203 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
204 };
205 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
206 if (ret != HKS_SUCCESS) {
207 ZLOGE("HksAddParams failed, status: %{public}d", ret);
208 HksFreeParamSet(¶ms);
209 return {};
210 }
211
212 ret = HksBuildParamSet(¶ms);
213 if (ret != HKS_SUCCESS) {
214 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
215 HksFreeParamSet(¶ms);
216 return {};
217 }
218
219 uint8_t cipherBuf[256] = { 0 };
220 struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf };
221 ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText);
222 (void)HksFreeParamSet(¶ms);
223 if (ret != HKS_SUCCESS) {
224 ZLOGE("HksEncrypt failed, status: %{public}d", ret);
225 return {};
226 }
227 std::vector<uint8_t> encryptedKey(cipherText.data, cipherText.data + cipherText.size);
228 (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf));
229 return encryptedKey;
230 }
231
Decrypt(std::vector<uint8_t> & source,std::vector<uint8_t> & key)232 bool SecurityManager::Decrypt(std::vector<uint8_t> &source, std::vector<uint8_t> &key)
233 {
234 struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) };
235 struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), &(vecNonce_[0]) };
236 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) };
237 struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() };
238
239 struct HksParamSet *params = nullptr;
240 int32_t ret = HksInitParamSet(¶ms);
241 if (ret != HKS_SUCCESS) {
242 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
243 return false;
244 }
245 struct HksParam hksParam[] = {
246 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
247 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
248 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
249 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
250 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
251 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
252 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
253 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
254 };
255 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
256 if (ret != HKS_SUCCESS) {
257 ZLOGE("HksAddParams failed, status: %{public}d", ret);
258 HksFreeParamSet(¶ms);
259 return false;
260 }
261
262 ret = HksBuildParamSet(¶ms);
263 if (ret != HKS_SUCCESS) {
264 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
265 HksFreeParamSet(¶ms);
266 return false;
267 }
268
269 uint8_t plainBuf[256] = { 0 };
270 struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf };
271 ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob);
272 (void)HksFreeParamSet(¶ms);
273 if (ret != HKS_SUCCESS) {
274 ZLOGE("HksDecrypt, status: %{public}d", ret);
275 return false;
276 }
277
278 key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size);
279 (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf));
280 return true;
281 }
282
GenerateRootKey()283 int32_t SecurityManager::GenerateRootKey()
284 {
285 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
286 struct HksParamSet *params = nullptr;
287 int32_t ret = HksInitParamSet(¶ms);
288 if (ret != HKS_SUCCESS) {
289 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
290 return ret;
291 }
292
293 struct HksParam hksParam[] = {
294 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
295 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
296 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
297 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
298 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
299 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
300 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
301 };
302
303 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
304 if (ret != HKS_SUCCESS) {
305 ZLOGE("HksAddParams failed, status: %{public}d", ret);
306 HksFreeParamSet(¶ms);
307 return ret;
308 }
309
310 ret = HksBuildParamSet(¶ms);
311 if (ret != HKS_SUCCESS) {
312 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
313 HksFreeParamSet(¶ms);
314 return ret;
315 }
316
317 ret = HksGenerateKey(&rootKeyName, params, nullptr);
318 HksFreeParamSet(¶ms);
319 ZLOGI("HksGenerateKey status: %{public}d", ret);
320 return ret;
321 }
322
CheckRootKey()323 int32_t SecurityManager::CheckRootKey()
324 {
325 struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
326 struct HksParamSet *params = nullptr;
327 int32_t ret = HksInitParamSet(¶ms);
328 if (ret != HKS_SUCCESS) {
329 ZLOGE("HksInitParamSet failed, status: %{public}d", ret);
330 return ret;
331 }
332
333 struct HksParam hksParam[] = {
334 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
335 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
336 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
337 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
338 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
339 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
340 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
341 };
342
343 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
344 if (ret != HKS_SUCCESS) {
345 ZLOGE("HksAddParams failed, status: %{public}d", ret);
346 HksFreeParamSet(¶ms);
347 return ret;
348 }
349
350 ret = HksBuildParamSet(¶ms);
351 if (ret != HKS_SUCCESS) {
352 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
353 HksFreeParamSet(¶ms);
354 return ret;
355 }
356
357 ret = HksKeyExist(&rootKeyName, params);
358 HksFreeParamSet(¶ms);
359 ZLOGI("HksKeyExist status: %{public}d", ret);
360 return ret;
361 }
362
IsKeyOutdated(const std::vector<uint8_t> & date)363 bool SecurityManager::IsKeyOutdated(const std::vector<uint8_t> &date)
364 {
365 time_t time = *reinterpret_cast<time_t *>(const_cast<uint8_t *>(&date[0]));
366 auto createTime = std::chrono::system_clock::from_time_t(time);
367 return ((createTime + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now());
368 }
369
370 } // namespace OHOS::DistributedKv
371