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 "RdbSecurityManager"
16 #include "rdb_security_manager.h"
17
18 #include <fcntl.h>
19 #include <securec.h>
20 #include <sys/file.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23
24 #include <string>
25
26 #include "directory_ex.h"
27 #include "file_ex.h"
28 #include "hks_api.h"
29 #include "hks_param.h"
30 #include "logger.h"
31 #include "rdb_errno.h"
32 #include "rdb_platform.h"
33 #include "rdb_sql_utils.h"
34 #include "sqlite_utils.h"
35 #include "string_utils.h"
36 #include "rdb_fault_hiview_reporter.h"
37
38 namespace OHOS {
39 namespace NativeRdb {
40 using namespace OHOS::Rdb;
41 using Reportor = RdbFaultHiViewReporter;
42
43 RdbPassword::RdbPassword() = default;
44
~RdbPassword()45 RdbPassword::~RdbPassword()
46 {
47 (void)Clear();
48 }
49
operator ==(const RdbPassword & input) const50 bool RdbPassword::operator==(const RdbPassword &input) const
51 {
52 if (size_ != input.GetSize()) {
53 return false;
54 }
55 return memcmp(data_, input.GetData(), size_) == 0;
56 }
57
operator !=(const RdbPassword & input) const58 bool RdbPassword::operator!=(const RdbPassword &input) const
59 {
60 return !(*this == input);
61 }
62
GetSize() const63 size_t RdbPassword::GetSize() const
64 {
65 return size_;
66 }
67
GetData() const68 const uint8_t *RdbPassword::GetData() const
69 {
70 return data_;
71 }
72
SetValue(const uint8_t * inputData,size_t inputSize)73 int RdbPassword::SetValue(const uint8_t *inputData, size_t inputSize)
74 {
75 if (inputSize > MAX_PASSWORD_SIZE) {
76 return E_ERROR;
77 }
78 if (inputSize != 0 && inputData == nullptr) {
79 return E_ERROR;
80 }
81
82 if (inputSize != 0) {
83 std::copy(inputData, inputData + inputSize, data_);
84 }
85
86 size_t filledSize = std::min(size_, MAX_PASSWORD_SIZE);
87 if (inputSize < filledSize) {
88 std::fill(data_ + inputSize, data_ + filledSize, UCHAR_MAX);
89 }
90
91 size_ = inputSize;
92 return E_OK;
93 }
94
Clear()95 int RdbPassword::Clear()
96 {
97 return SetValue(nullptr, 0);
98 }
99
IsValid() const100 bool RdbPassword::IsValid() const
101 {
102 return size_ != 0;
103 }
104
GetRootKeyAlias()105 std::vector<uint8_t> RdbSecurityManager::GetRootKeyAlias()
106 {
107 std::lock_guard<std::mutex> lock(rootKeyMutex_);
108 return rootKeyAlias_;
109 }
110
SetRootKeyAlias(std::vector<uint8_t> rootKeyAlias)111 void RdbSecurityManager::SetRootKeyAlias(std::vector<uint8_t> rootKeyAlias)
112 {
113 std::lock_guard<std::mutex> lock(rootKeyMutex_);
114 rootKeyAlias_ = std::move(rootKeyAlias);
115 }
116
GetBundleNameByAlias()117 std::string RdbSecurityManager::GetBundleNameByAlias()
118 {
119 auto rootKeyAlias = GetRootKeyAlias();
120 return GetBundleNameByAlias(rootKeyAlias);
121 }
122
GetBundleNameByAlias(const std::vector<uint8_t> & rootKeyAlias)123 std::string RdbSecurityManager::GetBundleNameByAlias(const std::vector<uint8_t> &rootKeyAlias)
124 {
125 auto prefixLen = strlen(RDB_ROOT_KEY_ALIAS_PREFIX);
126 if (rootKeyAlias.size() > prefixLen) {
127 return std::string(rootKeyAlias.begin() + prefixLen, rootKeyAlias.end());
128 }
129 return "";
130 }
131
HksLoopUpdate(const struct HksBlob * handle,const struct HksParamSet * paramSet,const struct HksBlob * inData,struct HksBlob * outData)132 int32_t RdbSecurityManager::HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet,
133 const struct HksBlob *inData, struct HksBlob *outData)
134 {
135 if (outData->size < inData->size * TIMES) {
136 HksAbort(handle, paramSet);
137 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(),
138 "HksLoopUpdate out size not enough"));
139 return HKS_ERROR_INVALID_ARGUMENT;
140 }
141
142 struct HksBlob input = { MAX_UPDATE_SIZE, inData->data };
143 uint8_t *end = inData->data + inData->size - 1;
144 outData->size = 0;
145 struct HksBlob output = { MAX_OUTDATA_SIZE, outData->data };
146 while (input.data <= end) {
147 if (input.data + MAX_UPDATE_SIZE > end) {
148 input.size = end - input.data + 1;
149 break;
150 }
151 auto result = HksUpdate(handle, paramSet, &input, &output);
152 if (result != HKS_SUCCESS) {
153 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(),
154 "HksUpdate ret=" + std::to_string(result)));
155 LOG_ERROR("HksUpdate Failed.");
156 return HKS_FAILURE;
157 }
158
159 output.data += output.size;
160 outData->size += output.size;
161 input.data += MAX_UPDATE_SIZE;
162 }
163 output.size = input.size * TIMES;
164 auto result = HksFinish(handle, paramSet, &input, &output);
165 if (result != HKS_SUCCESS) {
166 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(),
167 "HksFinish ret=" + std::to_string(result)));
168 LOG_ERROR("HksFinish Failed.");
169 return HKS_FAILURE;
170 }
171 outData->size += output.size;
172 return HKS_SUCCESS;
173 }
174
HksEncryptThreeStage(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet,const struct HksBlob * plainText,struct HksBlob * cipherText)175 int32_t RdbSecurityManager::HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
176 const struct HksBlob *plainText, struct HksBlob *cipherText)
177 {
178 uint8_t handle[sizeof(uint64_t)] = { 0 };
179 struct HksBlob handleBlob = { sizeof(uint64_t), handle };
180 int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr);
181 if (result != HKS_SUCCESS) {
182 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL,
183 GetBundleNameByAlias(), "Encrypt HksInit ret=" + std::to_string(result)));
184 LOG_ERROR("HksEncrypt failed with error %{public}d", result);
185 return result;
186 }
187 return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText);
188 }
189
HksDecryptThreeStage(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet,const struct HksBlob * cipherText,struct HksBlob * plainText)190 int32_t RdbSecurityManager::HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
191 const struct HksBlob *cipherText, struct HksBlob *plainText)
192 {
193 uint8_t handle[sizeof(uint64_t)] = { 0 };
194 struct HksBlob handleBlob = { sizeof(uint64_t), handle };
195 int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr);
196 if (result != HKS_SUCCESS) {
197 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(),
198 "Decrypt HksInit ret=" + std::to_string(result)));
199 LOG_ERROR("HksEncrypt failed with error %{public}d", result);
200 return result;
201 }
202 result = HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText);
203 if (result != HKS_SUCCESS) {
204 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(),
205 "Decrypt HksLoopUpdate ret=" + std::to_string(result)));
206 }
207 return result;
208 }
209
RdbSecurityManager()210 RdbSecurityManager::RdbSecurityManager()
211 : nonce_(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)),
212 aad_(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)) {};
213
214 RdbSecurityManager::~RdbSecurityManager() = default;
215
GenerateRandomNum(int32_t len)216 std::vector<uint8_t> RdbSecurityManager::GenerateRandomNum(int32_t len)
217 {
218 std::random_device randomDevice;
219 std::uniform_int_distribution<int> distribution(0, std::numeric_limits<uint8_t>::max());
220 std::vector<uint8_t> key(len);
221 for (int32_t i = 0; i < len; i++) {
222 key[i] = static_cast<uint8_t>(distribution(randomDevice));
223 }
224 return key;
225 }
226
SaveSecretKeyToFile(const std::string & keyFile,const std::vector<uint8_t> & workey)227 bool RdbSecurityManager::SaveSecretKeyToFile(const std::string &keyFile, const std::vector<uint8_t> &workey)
228 {
229 LOG_INFO("begin keyFile%{public}s.", SqliteUtils::Anonymous(keyFile).c_str());
230 if (!HasRootKey()) {
231 Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_ROOT_KEY_NOT_LOAD, GetBundleNameByAlias(), "not root key"));
232 LOG_ERROR("Root key not exists!");
233 return false;
234 }
235 std::vector<uint8_t> key = workey.empty() ? GenerateRandomNum(RDB_KEY_SIZE) : workey;
236 RdbSecretKeyData keyData;
237 keyData.timeValue = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now());
238 keyData.distributed = 0;
239 keyData.secretKey = EncryptWorkKey(key);
240
241 if (keyData.secretKey.empty()) {
242 Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_FAIL, GetBundleNameByAlias(), "key is empty"));
243 LOG_ERROR("Key size is 0");
244 key.assign(key.size(), 0);
245 return false;
246 }
247
248 key.assign(key.size(), 0);
249 return SaveSecretKeyToDisk(keyFile, keyData);
250 }
251
SaveSecretKeyToDisk(const std::string & keyPath,RdbSecretKeyData & keyData)252 bool RdbSecurityManager::SaveSecretKeyToDisk(const std::string &keyPath, RdbSecretKeyData &keyData)
253 {
254 LOG_INFO("begin keyPath:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str());
255 std::vector<uint8_t> distributedInByte = { &keyData.distributed, &keyData.distributed + sizeof(uint8_t) };
256 std::vector<uint8_t> timeInByte = { reinterpret_cast<uint8_t *>(&keyData.timeValue),
257 reinterpret_cast<uint8_t *>(&keyData.timeValue) + sizeof(time_t) };
258
259 std::vector<char> secretKeyInChar;
260 secretKeyInChar.insert(secretKeyInChar.end(), distributedInByte.begin(), distributedInByte.end());
261 secretKeyInChar.insert(secretKeyInChar.end(), timeInByte.begin(), timeInByte.end());
262 secretKeyInChar.insert(secretKeyInChar.end(), keyData.secretKey.begin(), keyData.secretKey.end());
263
264 bool ret;
265 {
266 std::lock_guard<std::mutex> lock(mutex_);
267 ret = SaveBufferToFile(keyPath, secretKeyInChar);
268 }
269 if (!ret) {
270 Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_FAIL, GetBundleNameByAlias(),
271 "save fail errno=" + std::to_string(errno)));
272 }
273 return ret;
274 }
275
GenerateRootKey(const std::vector<uint8_t> & rootKeyAlias)276 int RdbSecurityManager::GenerateRootKey(const std::vector<uint8_t> &rootKeyAlias)
277 {
278 LOG_INFO("RDB GenerateRootKey begin.");
279 std::vector<uint8_t> tempRootKeyAlias = rootKeyAlias;
280 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), tempRootKeyAlias.data() };
281 struct HksParamSet *params = nullptr;
282 int32_t ret = HksInitParamSet(¶ms);
283 if (ret != HKS_SUCCESS) {
284 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias),
285 "generator root key, HksInitParamSet ret=" + std::to_string(ret)));
286 LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret);
287 return ret;
288 }
289
290 struct HksParam hksParam[] = {
291 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
292 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
293 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
294 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
295 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
296 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
297 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
298 };
299
300 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
301 if (ret != HKS_SUCCESS) {
302 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias),
303 "HksAddParams ret=" + std::to_string(ret)));
304 LOG_ERROR("HksAddParams-client failed with error %{public}d", ret);
305 HksFreeParamSet(¶ms);
306 return ret;
307 }
308
309 ret = HksBuildParamSet(¶ms);
310 if (ret != HKS_SUCCESS) {
311 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias),
312 "HksBuildParamSet ret=" + std::to_string(ret)));
313 LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret);
314 HksFreeParamSet(¶ms);
315 return ret;
316 }
317
318 ret = HksGenerateKey(&rootKeyName, params, nullptr);
319 HksFreeParamSet(¶ms);
320 if (ret != HKS_SUCCESS) {
321 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias),
322 "HksGenerateKey ret=" + std::to_string(ret)));
323 LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret);
324 }
325 return ret;
326 }
327
EncryptWorkKey(std::vector<uint8_t> & key)328 std::vector<uint8_t> RdbSecurityManager::EncryptWorkKey(std::vector<uint8_t> &key)
329 {
330 std::vector<uint8_t> rootKeyAlias = GetRootKeyAlias();
331 struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() };
332 struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() };
333 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() };
334 struct HksBlob plainKey = { uint32_t(key.size()), key.data() };
335 struct HksParamSet *params = nullptr;
336 int32_t ret = HksInitParamSet(¶ms);
337 if (ret != HKS_SUCCESS) {
338 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias),
339 "Encrypt HksInitParamSet ret=" + std::to_string(ret)));
340 LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret);
341 return {};
342 }
343 struct HksParam hksParam[] = {{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
344 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
345 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
346 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
347 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
348 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
349 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
350 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }};
351
352 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
353 if (ret != HKS_SUCCESS) {
354 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias),
355 "Encrypt HksAddParams ret=" + std::to_string(ret)));
356 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
357 HksFreeParamSet(¶ms);
358 return {};
359 }
360
361 ret = HksBuildParamSet(¶ms);
362 if (ret != HKS_SUCCESS) {
363 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias),
364 "Encrypt HksBuildParamSet ret=" + std::to_string(ret)));
365 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
366 HksFreeParamSet(¶ms);
367 return {};
368 }
369 std::vector<uint8_t> encryptedKey(plainKey.size * TIMES + 1);
370 struct HksBlob cipherText = { uint32_t(encryptedKey.size()), encryptedKey.data() };
371 ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText);
372 (void)HksFreeParamSet(¶ms);
373 if (ret != HKS_SUCCESS) {
374 encryptedKey.assign(encryptedKey.size(), 0);
375 LOG_ERROR("HksEncrypt failed with error %{public}d", ret);
376 return {};
377 }
378 encryptedKey.resize(cipherText.size);
379 return encryptedKey;
380 }
381
DecryptWorkKey(std::vector<uint8_t> & source,std::vector<uint8_t> & key)382 bool RdbSecurityManager::DecryptWorkKey(std::vector<uint8_t> &source, std::vector<uint8_t> &key)
383 {
384 std::vector<uint8_t> rootKeyAlias = GetRootKeyAlias();
385 struct HksBlob blobAad = { uint32_t(aad_.size()), &(aad_[0]) };
386 struct HksBlob blobNonce = { uint32_t(nonce_.size()), &(nonce_[0]) };
387 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), &(rootKeyAlias[0]) };
388 struct HksBlob encryptedKeyBlob = { uint32_t(source.size() - AEAD_LEN), source.data() };
389 struct HksBlob blobAead = { AEAD_LEN, source.data() + source.size() - AEAD_LEN };
390 struct HksParamSet *params = nullptr;
391 int32_t ret = HksInitParamSet(¶ms);
392 if (ret != HKS_SUCCESS) {
393 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias),
394 "HksInitParamSet ret=" + std::to_string(ret)));
395 LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret);
396 return false;
397 }
398 struct HksParam hksParam[] = {
399 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
400 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
401 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
402 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
403 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
404 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
405 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
406 { .tag = HKS_TAG_AE_TAG, .blob = blobAead },
407 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
408 };
409 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
410 if (ret != HKS_SUCCESS) {
411 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias),
412 "HksAddParams ret=" + std::to_string(ret)));
413 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
414 HksFreeParamSet(¶ms);
415 return false;
416 }
417
418 ret = HksBuildParamSet(¶ms);
419 if (ret != HKS_SUCCESS) {
420 Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias),
421 "HksBuildParamSet ret=" + std::to_string(ret)));
422 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
423 HksFreeParamSet(¶ms);
424 return false;
425 }
426 key.resize(encryptedKeyBlob.size * TIMES + 1);
427 struct HksBlob plainKeyBlob = { uint32_t(key.size()), key.data() };
428 ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob);
429 (void)HksFreeParamSet(¶ms);
430 if (ret != HKS_SUCCESS) {
431 key.assign(key.size(), 0);
432 LOG_ERROR("HksDecrypt failed with error %{public}d", ret);
433 return false;
434 }
435 key.resize(plainKeyBlob.size);
436 return true;
437 }
438
Init(const std::string & bundleName)439 int32_t RdbSecurityManager::Init(const std::string &bundleName)
440 {
441 std::vector<uint8_t> rootKeyAlias = GenerateRootKeyAlias(bundleName);
442 constexpr uint32_t RETRY_MAX_TIMES = 5;
443 constexpr int RETRY_TIME_INTERVAL_MILLISECOND = 1 * 1000 * 1000;
444 int32_t ret = HKS_FAILURE;
445 uint32_t retryCount = 0;
446 while (retryCount < RETRY_MAX_TIMES) {
447 ret = CheckRootKeyExists(rootKeyAlias);
448 if (ret == HKS_ERROR_NOT_EXIST) {
449 hasRootKey_ = false;
450 ret = GenerateRootKey(rootKeyAlias);
451 }
452 if (ret == HKS_SUCCESS) {
453 if (!HasRootKey()) {
454 hasRootKey_ = true;
455 }
456 SetRootKeyAlias(std::move(rootKeyAlias));
457 break;
458 }
459 retryCount++;
460 usleep(RETRY_TIME_INTERVAL_MILLISECOND);
461 }
462 LOG_INFO("bundleName:%{public}s, retry:%{public}u, error:%{public}d", bundleName.c_str(), retryCount, ret);
463 return ret;
464 }
465
CheckRootKeyExists(std::vector<uint8_t> & rootKeyAlias)466 int32_t RdbSecurityManager::CheckRootKeyExists(std::vector<uint8_t> &rootKeyAlias)
467 {
468 LOG_DEBUG("RDB checkRootKeyExist begin.");
469 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() };
470 struct HksParamSet *params = nullptr;
471 int32_t ret = HksInitParamSet(¶ms);
472 if (ret != HKS_SUCCESS) {
473 LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret);
474 return ret;
475 }
476
477 struct HksParam hksParam[] = {
478 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
479 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
480 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
481 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
482 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
483 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
484 { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
485 };
486
487 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
488 if (ret != HKS_SUCCESS) {
489 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
490 HksFreeParamSet(¶ms);
491 return ret;
492 }
493
494 ret = HksBuildParamSet(¶ms);
495 if (ret != HKS_SUCCESS) {
496 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
497 HksFreeParamSet(¶ms);
498 return ret;
499 }
500
501 ret = HksKeyExist(&rootKeyName, params);
502 HksFreeParamSet(¶ms);
503 return ret;
504 }
505
InitPath(const std::string & fileDir)506 bool RdbSecurityManager::InitPath(const std::string &fileDir)
507 {
508 constexpr mode_t DEFAULT_UMASK = 0002;
509 if (access(fileDir.c_str(), F_OK) == 0) {
510 return true;
511 }
512 umask(DEFAULT_UMASK);
513 auto ret = MkDir(fileDir, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH));
514 if (ret != 0 && errno != EEXIST) {
515 Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_FAIL,
516 RdbSecurityManager::GetInstance().GetBundleNameByAlias(),
517 "mkdir err, ret=" + std::to_string(ret) + ",errno=" + std::to_string(errno) +
518 ",fileDir=" + SqliteUtils::Anonymous(fileDir)));
519 LOG_ERROR("mkdir error:%{public}d, dbDir:%{public}s", errno, SqliteUtils::Anonymous(fileDir).c_str());
520 return false;
521 }
522 return true;
523 }
524
LoadSecretKeyFromFile(const std::string & keyFile)525 RdbPassword RdbSecurityManager::LoadSecretKeyFromFile(const std::string &keyFile)
526 {
527 auto ret = access(keyFile.c_str(), F_OK);
528 if (ret != 0) {
529 auto anonymousFile = SqliteUtils::Anonymous(keyFile);
530 Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(),
531 "access " + anonymousFile + " fail, ret=" + std::to_string(ret) + ",errno=" + std::to_string(errno)));
532 LOG_ERROR("Not exists. errno:%{public}d, file:%{public}s", errno, anonymousFile.c_str());
533 return {};
534 }
535
536 RdbSecretKeyData keyData;
537 if (!LoadSecretKeyFromDisk(keyFile, keyData)) {
538 Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(),
539 "LoadSecretKeyFromDisk fail,errno=" + std::to_string(errno)));
540 LOG_ERROR("Load key failed.");
541 return {};
542 }
543
544 std::vector<uint8_t> key;
545 if (!DecryptWorkKey(keyData.secretKey, key)) {
546 Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(),
547 "DecryptWorkKey fail,errno=" + std::to_string(errno)));
548 LOG_ERROR("Decrypt key failed!");
549 return {};
550 }
551
552 RdbPassword rdbPasswd;
553 rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue);
554 rdbPasswd.SetValue(key.data(), key.size());
555 key.assign(key.size(), 0);
556 return rdbPasswd;
557 }
558
LoadSecretKeyFromDisk(const std::string & keyPath,RdbSecretKeyData & keyData)559 bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData)
560 {
561 LOG_DEBUG("begin keyPath:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str());
562 std::vector<char> content;
563 {
564 std::lock_guard<std::mutex> lock(mutex_);
565 if (!LoadBufferFromFile(keyPath, content) || content.empty()) {
566 Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(),
567 "LoadBufferFromFile fail, errno=" + std::to_string(errno)));
568 LOG_ERROR("LoadBufferFromFile failed!");
569 return false;
570 }
571 }
572
573 auto size = content.size();
574 std::size_t offset = 0;
575 auto iter = content.begin();
576 if (offset + 1 >= static_cast<std::size_t>(size)) {
577 return false;
578 }
579 keyData.distributed = *iter;
580 iter++;
581 offset++;
582
583 std::vector<uint8_t> createTime;
584 if (offset + static_cast<std::size_t>(sizeof(time_t) / sizeof(uint8_t)) >= size) {
585 return false;
586 }
587 offset += sizeof(time_t) / sizeof(uint8_t);
588 for (std::size_t i = 0; i < sizeof(time_t) / sizeof(uint8_t); i++) {
589 createTime.push_back(*iter);
590 iter++;
591 }
592
593 if (createTime.size() == sizeof(time_t)) {
594 keyData.timeValue = *reinterpret_cast<time_t *>(&createTime[0]);
595 }
596
597 if (offset + AEAD_LEN >= static_cast<std::size_t>(size)) {
598 return false;
599 }
600 offset = size;
601 keyData.secretKey.insert(keyData.secretKey.end(), iter, content.end());
602
603 return true;
604 }
605
GetRdbPassword(const std::string & dbPath,KeyFileType keyFileType)606 RdbPassword RdbSecurityManager::GetRdbPassword(const std::string &dbPath, KeyFileType keyFileType)
607 {
608 KeyFiles keyFiles(dbPath);
609 keyFiles.Lock();
610 auto &keyFile = keyFiles.GetKeyFile(keyFileType);
611 if (IsKeyFileEmpty(keyFile)) {
612 keyFiles.InitKeyPath();
613 if (!SaveSecretKeyToFile(keyFile)) {
614 keyFiles.Unlock();
615 LOG_ERROR("Failed to save key type:%{public}d err:%{public}d.", keyFileType, errno);
616 return {};
617 }
618 }
619 keyFiles.Unlock();
620 return LoadSecretKeyFromFile(keyFile);
621 }
622
GenerateRootKeyAlias(const std::string & bundlename)623 std::vector<uint8_t> RdbSecurityManager::GenerateRootKeyAlias(const std::string &bundlename)
624 {
625 std::vector<uint8_t> rootKeyAlias =
626 std::vector<uint8_t>(RDB_ROOT_KEY_ALIAS_PREFIX, RDB_ROOT_KEY_ALIAS_PREFIX + strlen(RDB_ROOT_KEY_ALIAS_PREFIX));
627 rootKeyAlias.insert(rootKeyAlias.end(), bundlename.begin(), bundlename.end());
628 return rootKeyAlias;
629 }
630
DelAllKeyFiles(const std::string & dbPath)631 void RdbSecurityManager::DelAllKeyFiles(const std::string &dbPath)
632 {
633 LOG_INFO("Delete all key files begin.");
634 const std::string dbKeyDir = StringUtils::ExtractFilePath(dbPath) + "key/";
635 if (access(dbKeyDir.c_str(), F_OK) != 0) {
636 return;
637 }
638 KeyFiles keyFiles(dbPath);
639 keyFiles.Lock();
640 {
641 std::lock_guard<std::mutex> lock(mutex_);
642 SqliteUtils::DeleteFile(keyFiles.GetKeyFile(PUB_KEY_FILE));
643 SqliteUtils::DeleteFile(keyFiles.GetKeyFile(PUB_KEY_FILE_NEW_KEY));
644 }
645 keyFiles.Unlock();
646 keyFiles.DestroyLock();
647 }
648
DelKeyFile(const std::string & dbPath,KeyFileType keyFileType)649 void RdbSecurityManager::DelKeyFile(const std::string &dbPath, KeyFileType keyFileType)
650 {
651 KeyFiles keyFiles(dbPath);
652 keyFiles.Lock();
653 {
654 std::lock_guard<std::mutex> lock(mutex_);
655 SqliteUtils::DeleteFile(keyFiles.GetKeyFile(keyFileType));
656 }
657 keyFiles.Unlock();
658 }
659
IsKeyExpired(const time_t & createTime)660 bool RdbSecurityManager::IsKeyExpired(const time_t &createTime)
661 {
662 auto timePoint = std::chrono::system_clock::from_time_t(createTime);
663 return ((timePoint + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now());
664 }
665
GetInstance()666 RdbSecurityManager &RdbSecurityManager::GetInstance()
667 {
668 static RdbSecurityManager instance;
669 return instance;
670 }
671
RemoveSuffix(const std::string & name)672 static std::string RemoveSuffix(const std::string &name)
673 {
674 std::string suffix(".db");
675 auto pos = name.rfind(suffix);
676 if (pos == std::string::npos || pos < name.length() - suffix.length()) {
677 return name;
678 }
679 return { name, 0, pos };
680 }
681
IsKeyFileExists(const std::string & dbPath,KeyFileType keyFileType)682 bool RdbSecurityManager::IsKeyFileExists(const std::string &dbPath, KeyFileType keyFileType)
683 {
684 KeyFiles keyFiles(dbPath, false);
685 return (access(keyFiles.GetKeyFile(keyFileType).c_str(), F_OK) == 0);
686 }
687
ChangeKeyFile(const std::string & dbPath)688 void RdbSecurityManager::ChangeKeyFile(const std::string &dbPath)
689 {
690 KeyFiles keyFiles(dbPath);
691 keyFiles.Lock();
692 auto &reKeyFile = keyFiles.GetKeyFile(PUB_KEY_FILE_NEW_KEY);
693 auto &keyFile = keyFiles.GetKeyFile(PUB_KEY_FILE);
694 SqliteUtils::RenameFile(reKeyFile, keyFile);
695 keyFiles.Unlock();
696 }
697
HasRootKey()698 bool RdbSecurityManager::HasRootKey()
699 {
700 return hasRootKey_;
701 }
702
IsKeyFileEmpty(const std::string & keyFile)703 bool RdbSecurityManager::IsKeyFileEmpty(const std::string &keyFile)
704 {
705 struct stat fileInfo;
706 auto errCode = stat(keyFile.c_str(), &fileInfo);
707 if (errCode != 0) {
708 return true;
709 }
710 return fileInfo.st_size == 0;
711 }
712
RestoreKeyFile(const std::string & dbPath,const std::vector<uint8_t> & key)713 int32_t RdbSecurityManager::RestoreKeyFile(const std::string &dbPath, const std::vector<uint8_t> &key)
714 {
715 KeyFiles keyFiles(dbPath);
716 keyFiles.Lock();
717 auto &keyFile = keyFiles.GetKeyFile(PUB_KEY_FILE);
718 auto &reKeyFile = keyFiles.GetKeyFile(PUB_KEY_FILE_NEW_KEY);
719 {
720 std::lock_guard<std::mutex> lock(mutex_);
721 SqliteUtils::DeleteFile(keyFile);
722 SqliteUtils::DeleteFile(reKeyFile);
723 }
724 if (!SaveSecretKeyToFile(keyFile, key)) {
725 LOG_ERROR("failed, save key err:%{public}d, file:%{public}s.", errno, SqliteUtils::Anonymous(keyFile).c_str());
726 }
727 keyFiles.Unlock();
728 return E_OK;
729 }
730
KeyFiles(const std::string & dbPath,bool openFile)731 RdbSecurityManager::KeyFiles::KeyFiles(const std::string &dbPath, bool openFile)
732 {
733 const std::string dbKeyDir = StringUtils::ExtractFilePath(dbPath) + "key/";
734 const std::string lockDir = StringUtils::ExtractFilePath(dbPath) + "lock/";
735 if (!InitPath(lockDir)) {
736 LOG_ERROR("lockDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lockDir).c_str());
737 }
738 const std::string dbName = RemoveSuffix(StringUtils::ExtractFileName(dbPath));
739 lock_ = lockDir + dbName + SUFFIX_KEY_LOCK;
740 keys_[PUB_KEY_FILE] = dbKeyDir + dbName + SUFFIX_PUB_KEY;
741 keys_[PUB_KEY_FILE_NEW_KEY] = dbKeyDir + dbName + SUFFIX_PUB_KEY_NEW;
742 if (!openFile) {
743 return;
744 }
745 lockFd_ = open(lock_.c_str(), O_RDONLY | O_CREAT, S_IRWXU | S_IRWXG);
746 if (lockFd_ < 0) {
747 LOG_WARN("open failed, errno:%{public}d, file:%{public}s.", errno, SqliteUtils::Anonymous(lock_).c_str());
748 }
749 }
750
~KeyFiles()751 RdbSecurityManager::KeyFiles::~KeyFiles()
752 {
753 if (lockFd_ < 0) {
754 return;
755 }
756 close(lockFd_);
757 lockFd_ = -1;
758 }
759
GetKeyFile(KeyFileType type)760 const std::string &RdbSecurityManager::KeyFiles::GetKeyFile(KeyFileType type)
761 {
762 if (type == PUB_KEY_FILE) {
763 return keys_[PUB_KEY_FILE];
764 }
765 return keys_[PUB_KEY_FILE_NEW_KEY];
766 }
767
InitKeyPath()768 int32_t RdbSecurityManager::KeyFiles::InitKeyPath()
769 {
770 const std::string keyDir = StringUtils::ExtractFilePath(keys_[PUB_KEY_FILE]);
771 if (!InitPath(keyDir)) {
772 LOG_ERROR("keyDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(keyDir).c_str());
773 }
774 return E_OK;
775 }
776
Lock()777 int32_t RdbSecurityManager::KeyFiles::Lock()
778 {
779 if (lockFd_ < 0) {
780 return E_INVALID_FILE_PATH;
781 }
782 int32_t errCode;
783 do {
784 errCode = flock(lockFd_, LOCK_EX);
785 } while (errCode < 0 && errno == EINTR);
786 if (errCode < 0) {
787 LOG_WARN("lock failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lock_).c_str());
788 return E_ERROR;
789 }
790 return E_OK;
791 }
792
Unlock()793 int32_t RdbSecurityManager::KeyFiles::Unlock()
794 {
795 if (lockFd_ < 0) {
796 return E_INVALID_FILE_PATH;
797 }
798 int32_t errCode;
799 do {
800 errCode = flock(lockFd_, LOCK_UN);
801 } while (errCode < 0 && errno == EINTR);
802 if (errCode < 0) {
803 LOG_WARN("unlock failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lock_).c_str());
804 return E_ERROR;
805 }
806 return E_OK;
807 }
808
DestroyLock()809 int32_t RdbSecurityManager::KeyFiles::DestroyLock()
810 {
811 if (lockFd_ >= 0) {
812 close(lockFd_);
813 lockFd_ = -1;
814 }
815 SqliteUtils::DeleteFile(lock_);
816 return E_OK;
817 }
818 } // namespace NativeRdb
819 } // namespace OHOS
820