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(¶ms);
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(¶ms);
204 return {};
205 }
206
207 ret = HksBuildParamSet(¶ms);
208 if (ret != HKS_SUCCESS) {
209 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
210 HksFreeParamSet(¶ms);
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(¶ms);
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(¶ms);
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(¶ms);
253 return false;
254 }
255
256 ret = HksBuildParamSet(¶ms);
257 if (ret != HKS_SUCCESS) {
258 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
259 HksFreeParamSet(¶ms);
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(¶ms);
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(¶ms);
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(¶ms);
300 return ret;
301 }
302
303 ret = HksBuildParamSet(¶ms);
304 if (ret != HKS_SUCCESS) {
305 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
306 HksFreeParamSet(¶ms);
307 return ret;
308 }
309
310 ret = HksGenerateKey(&rootKeyName, params, nullptr);
311 HksFreeParamSet(¶ms);
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(¶ms);
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(¶ms);
339 return ret;
340 }
341
342 ret = HksBuildParamSet(¶ms);
343 if (ret != HKS_SUCCESS) {
344 ZLOGE("HksBuildParamSet failed, status: %{public}d", ret);
345 HksFreeParamSet(¶ms);
346 return ret;
347 }
348
349 ret = HksKeyExist(&rootKeyName, params);
350 HksFreeParamSet(¶ms);
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