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
16 #include "rdb_security_manager.h"
17
18 #include <securec.h>
19
20 #include <string>
21 #include <utility>
22
23 #include "directory_ex.h"
24 #include "file_ex.h"
25 #include "hks_param.h"
26 #include "logger.h"
27 #include "rdb_sql_utils.h"
28 #include "sqlite_utils.h"
29
30 #define HKS_FREE(PTR) \
31 { \
32 if ((PTR) != nullptr) { \
33 free(PTR); \
34 (PTR) = nullptr; \
35 } \
36 }
37
38 namespace OHOS {
39 namespace NativeRdb {
40 using namespace OHOS::Rdb;
41
42 RdbPassword::RdbPassword() = default;
43
~RdbPassword()44 RdbPassword::~RdbPassword()
45 {
46 (void)Clear();
47 }
48
operator ==(const RdbPassword & input) const49 bool RdbPassword::operator==(const RdbPassword &input) const
50 {
51 if (size_ != input.GetSize()) {
52 return false;
53 }
54 return memcmp(data_, input.GetData(), size_) == 0;
55 }
56
operator !=(const RdbPassword & input) const57 bool RdbPassword::operator!=(const RdbPassword &input) const
58 {
59 return !(*this == input);
60 }
61
GetSize() const62 size_t RdbPassword::GetSize() const
63 {
64 return size_;
65 }
66
GetData() const67 const uint8_t *RdbPassword::GetData() const
68 {
69 return data_;
70 }
71
SetValue(const uint8_t * inputData,size_t inputSize)72 int RdbPassword::SetValue(const uint8_t *inputData, size_t inputSize)
73 {
74 if (inputSize > MAX_PASSWORD_SIZE) {
75 return E_ERROR;
76 }
77 if (inputSize != 0 && inputData == nullptr) {
78 return E_ERROR;
79 }
80
81 if (inputSize != 0) {
82 std::copy(inputData, inputData + inputSize, data_);
83 }
84
85 size_t filledSize = std::min(size_, MAX_PASSWORD_SIZE);
86 if (inputSize < filledSize) {
87 std::fill(data_ + inputSize, data_ + filledSize, UCHAR_MAX);
88 }
89
90 size_ = inputSize;
91 return E_OK;
92 }
93
Clear()94 int RdbPassword::Clear()
95 {
96 return SetValue(nullptr, 0);
97 }
98
IsValid() const99 bool RdbPassword::IsValid() const
100 {
101 return size_ != 0;
102 }
103
MallocAndCheckBlobData(struct HksBlob * blob,const uint32_t blobSize)104 int32_t RdbSecurityManager::MallocAndCheckBlobData(struct HksBlob *blob, const uint32_t blobSize)
105 {
106 blob->data = (uint8_t *)malloc(blobSize);
107 if (blob->data == NULL) {
108 LOG_ERROR("Blob data is NULL.");
109 return HKS_FAILURE;
110 }
111 return HKS_SUCCESS;
112 }
113
HksLoopUpdate(const struct HksBlob * handle,const struct HksParamSet * paramSet,const struct HksBlob * inData,struct HksBlob * outData)114 int32_t RdbSecurityManager::HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet,
115 const struct HksBlob *inData, struct HksBlob *outData)
116 {
117 struct HksBlob inDataSeg = *inData;
118 uint8_t *lastPtr = inData->data + inData->size - 1;
119 struct HksBlob outDataSeg = { MAX_OUTDATA_SIZE, NULL };
120 uint8_t *cur = outData->data;
121 outData->size = 0;
122
123 inDataSeg.size = MAX_UPDATE_SIZE;
124
125 while (inDataSeg.data <= lastPtr) {
126 if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) {
127 outDataSeg.size = MAX_OUTDATA_SIZE;
128 } else {
129 inDataSeg.size = lastPtr - inDataSeg.data + 1;
130 break;
131 }
132 if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size) != HKS_SUCCESS) {
133 LOG_ERROR("MallocAndCheckBlobData outDataSeg Failed.");
134 return HKS_FAILURE;
135 }
136 if (HksUpdate(handle, paramSet, &inDataSeg, &outDataSeg) != HKS_SUCCESS) {
137 LOG_ERROR("HksUpdate Failed.");
138 HKS_FREE(outDataSeg.data);
139 return HKS_FAILURE;
140 }
141 if (memcpy_s(cur, outDataSeg.size, outDataSeg.data, outDataSeg.size) != 0) {
142 LOG_ERROR("Method memcpy_s failed");
143 HKS_FREE(outDataSeg.data);
144 return HKS_FAILURE;
145 }
146 cur += outDataSeg.size;
147 outData->size += outDataSeg.size;
148 HKS_FREE(outDataSeg.data);
149 if (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr) {
150 LOG_ERROR("inDataSeg data Error");
151 return HKS_FAILURE;
152 }
153 inDataSeg.data += MAX_UPDATE_SIZE;
154 }
155
156 struct HksBlob outDataFinish = { inDataSeg.size * TIMES, NULL };
157 if (MallocAndCheckBlobData(&outDataFinish, outDataFinish.size) != HKS_SUCCESS) {
158 LOG_ERROR("MallocAndCheckBlobData outDataFinish Failed.");
159 return HKS_FAILURE;
160 }
161 if (HksFinish(handle, paramSet, &inDataSeg, &outDataFinish) != HKS_SUCCESS) {
162 LOG_ERROR("HksFinish Failed.");
163 HKS_FREE(outDataFinish.data);
164 return HKS_FAILURE;
165 }
166 if (memcpy_s(cur, outDataFinish.size, outDataFinish.data, outDataFinish.size) != 0) {
167 LOG_ERROR("Method memcpy_s failed");
168 HKS_FREE(outDataFinish.data);
169 return HKS_FAILURE;
170 }
171 outData->size += outDataFinish.size;
172 HKS_FREE(outDataFinish.data);
173
174 return HKS_SUCCESS;
175 }
176
HksEncryptThreeStage(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet,const struct HksBlob * plainText,struct HksBlob * cipherText)177 int32_t RdbSecurityManager::HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
178 const struct HksBlob *plainText, struct HksBlob *cipherText)
179 {
180 uint8_t handle[sizeof(uint64_t)] = { 0 };
181 struct HksBlob handleBlob = { sizeof(uint64_t), handle };
182 int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr);
183 if (result != HKS_SUCCESS) {
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 LOG_ERROR("HksEncrypt failed with error %{public}d", result);
198 return result;
199 }
200 return HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText);
201 }
202
203 RdbSecurityManager::RdbSecurityManager() = default;
204
205 RdbSecurityManager::~RdbSecurityManager() = default;
206
GenerateRandomNum(int32_t len)207 std::vector<uint8_t> RdbSecurityManager::GenerateRandomNum(int32_t len)
208 {
209 std::random_device randomDevice;
210 std::uniform_int_distribution<int> distribution(0, std::numeric_limits<uint8_t>::max());
211 std::vector<uint8_t> key(len);
212 for (int32_t i = 0; i < len; i++) {
213 key[i] = static_cast<uint8_t>(distribution(randomDevice));
214 }
215 return key;
216 }
217
SaveSecretKeyToFile(RdbSecurityManager::KeyFileType keyFile)218 bool RdbSecurityManager::SaveSecretKeyToFile(RdbSecurityManager::KeyFileType keyFile)
219 {
220 LOG_INFO("SaveSecretKeyToFile begin.");
221 if (!CheckRootKeyExists()) {
222 LOG_ERROR("Root key not exists!");
223 return false;
224 }
225 std::vector<uint8_t> key = GenerateRandomNum(RDB_KEY_SIZE);
226 RdbSecretKeyData keyData;
227 keyData.timeValue = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now());
228 keyData.distributed = 0;
229 keyData.secretKey = EncryptWorkKey(key);
230
231 if (keyData.secretKey.empty()) {
232 LOG_ERROR("Key size is 0");
233 key.assign(key.size(), 0);
234 return false;
235 }
236
237 key.assign(key.size(), 0);
238 if (!RdbSecurityManager::InitPath(dbKeyDir_)) {
239 LOG_ERROR("InitPath err.");
240 return false;
241 }
242
243 std::string keyPath;
244 GetKeyPath(keyFile, keyPath);
245
246 return SaveSecretKeyToDisk(keyPath, keyData);
247 }
248
SaveSecretKeyToDisk(const std::string & path,RdbSecretKeyData & keyData)249 bool RdbSecurityManager::SaveSecretKeyToDisk(const std::string &path, RdbSecretKeyData &keyData)
250 {
251 LOG_INFO("SaveSecretKeyToDisk begin.");
252 std::vector<uint8_t> distributedInByte = TransferTypeToByteArray<uint8_t>(keyData.distributed);
253 std::vector<uint8_t> timeInByte = TransferTypeToByteArray<time_t>(keyData.timeValue);
254 std::vector<char> secretKeyInChar;
255 secretKeyInChar.insert(secretKeyInChar.end(), distributedInByte.begin(), distributedInByte.end());
256 secretKeyInChar.insert(secretKeyInChar.end(), timeInByte.begin(), timeInByte.end());
257 secretKeyInChar.insert(secretKeyInChar.end(), keyData.secretKey.begin(), keyData.secretKey.end());
258
259 std::lock_guard<std::mutex> lock(mutex_);
260 bool ret = SaveBufferToFile(path, secretKeyInChar);
261 if (!ret) {
262 LOG_ERROR("SaveBufferToFile failed!");
263 return false;
264 }
265
266 return true;
267 }
268
GenerateRootKey()269 int RdbSecurityManager::GenerateRootKey()
270 {
271 LOG_INFO("RDB GenerateRootKey begin.");
272 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() };
273 struct HksParamSet *params = nullptr;
274 int32_t ret = HksInitParamSet(¶ms);
275 if (ret != HKS_SUCCESS) {
276 LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret);
277 return ret;
278 }
279
280 struct HksParam hksParam[] = {
281 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
282 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
283 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
284 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
285 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
286 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
287 };
288
289 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
290 if (ret != HKS_SUCCESS) {
291 LOG_ERROR("HksAddParams-client failed with error %{public}d", ret);
292 HksFreeParamSet(¶ms);
293 return ret;
294 }
295
296 ret = HksBuildParamSet(¶ms);
297 if (ret != HKS_SUCCESS) {
298 LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret);
299 HksFreeParamSet(¶ms);
300 return ret;
301 }
302
303 ret = HksGenerateKey(&rootKeyName, params, nullptr);
304 HksFreeParamSet(¶ms);
305 if (ret != HKS_SUCCESS) {
306 LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret);
307 }
308 LOG_INFO("RDB root key generated successful.");
309 return ret;
310 }
311
EncryptWorkKey(const std::vector<uint8_t> & key)312 std::vector<uint8_t> RdbSecurityManager::EncryptWorkKey(const std::vector<uint8_t> &key)
313 {
314 struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() };
315 struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() };
316 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() };
317 struct HksBlob plainKey = { uint32_t(key.size()), const_cast<uint8_t *>(key.data()) };
318 struct HksParamSet *params = nullptr;
319 int32_t ret = HksInitParamSet(¶ms);
320 if (ret != HKS_SUCCESS) {
321 LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret);
322 return {};
323 }
324 struct HksParam hksParam[] = {
325 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
326 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
327 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
328 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
329 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
330 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
331 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
332 };
333 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
334 if (ret != HKS_SUCCESS) {
335 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
336 HksFreeParamSet(¶ms);
337 return {};
338 }
339
340 ret = HksBuildParamSet(¶ms);
341 if (ret != HKS_SUCCESS) {
342 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
343 HksFreeParamSet(¶ms);
344 return {};
345 }
346
347 uint8_t cipherBuf[256] = { 0 };
348 struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf };
349 ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText);
350 (void)HksFreeParamSet(¶ms);
351 if (ret != HKS_SUCCESS) {
352 LOG_ERROR("HksEncrypt failed with error %{public}d", ret);
353 return {};
354 }
355
356 std::vector<uint8_t> encryptedKey(cipherText.data, cipherText.data + cipherText.size);
357 (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf));
358
359 return encryptedKey;
360 }
361
DecryptWorkKey(std::vector<uint8_t> & source,std::vector<uint8_t> & key)362 bool RdbSecurityManager::DecryptWorkKey(std::vector<uint8_t> &source, std::vector<uint8_t> &key)
363 {
364 uint8_t aead_[AEAD_LEN] = { 0 };
365 struct HksBlob blobAad = { uint32_t(aad_.size()), &(aad_[0]) };
366 struct HksBlob blobNonce = { uint32_t(nonce_.size()), &(nonce_[0]) };
367 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), &(rootKeyAlias_[0]) };
368 struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() };
369 struct HksBlob blobAead = { AEAD_LEN, aead_ };
370
371 struct HksParamSet *params = nullptr;
372 int32_t ret = HksInitParamSet(¶ms);
373 if (ret != HKS_SUCCESS) {
374 LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret);
375 return false;
376 }
377 struct HksParam hksParam[] = {
378 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
379 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
380 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
381 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
382 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
383 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
384 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
385 { .tag = HKS_TAG_AE_TAG, .blob = blobAead },
386 };
387 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
388 if (ret != HKS_SUCCESS) {
389 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
390 HksFreeParamSet(¶ms);
391 return false;
392 }
393
394 ret = HksBuildParamSet(¶ms);
395 if (ret != HKS_SUCCESS) {
396 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
397 HksFreeParamSet(¶ms);
398 return false;
399 }
400
401 encryptedKeyBlob.size -= AEAD_LEN;
402 for (uint32_t i = 0; i < params->paramsCnt; i++) {
403 if (params->params[i].tag == HKS_TAG_AE_TAG) {
404 uint8_t *tempPtr = encryptedKeyBlob.data;
405 if (memcpy_s(params->params[i].blob.data, AEAD_LEN, tempPtr + encryptedKeyBlob.size, AEAD_LEN) != 0) {
406 LOG_ERROR("Method memcpy_s failed");
407 HksFreeParamSet(¶ms);
408 return false;
409 }
410 break;
411 }
412 }
413
414 uint8_t plainBuf[256] = { 0 };
415 struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf };
416 ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob);
417 (void)HksFreeParamSet(¶ms);
418 if (ret != HKS_SUCCESS) {
419 LOG_ERROR("HksDecrypt failed with error %{public}d", ret);
420 return false;
421 }
422
423 key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size);
424 (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf));
425 return true;
426 }
427
Init(const std::string & bundleName,const std::string & path)428 void RdbSecurityManager::Init(const std::string &bundleName, const std::string &path)
429 {
430 ParsePath(path);
431 bundleName_ = bundleName;
432 rootKeyAlias_ = GenerateRootKeyAlias();
433 nonce_ = std::vector<uint8_t>(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE));
434 aad_ = std::vector<uint8_t>(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD));
435
436 if (CheckRootKeyExists()) {
437 return;
438 }
439 constexpr uint32_t RETRY_MAX_TIMES = 5;
440 uint32_t retryCount = 0;
441 constexpr int RETRY_TIME_INTERVAL_MILLISECOND = 1 * 1000 * 1000;
442 while (retryCount < RETRY_MAX_TIMES) {
443 auto ret = GenerateRootKey();
444 if (ret == HKS_SUCCESS) {
445 break;
446 }
447 retryCount++;
448 LOG_ERROR("RDB generate root key failed, try count:%{public}u", retryCount);
449 usleep(RETRY_TIME_INTERVAL_MILLISECOND);
450 }
451 }
452
CheckRootKeyExists()453 bool RdbSecurityManager::CheckRootKeyExists()
454 {
455 LOG_INFO("RDB checkRootKeyExist begin.");
456 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() };
457 struct HksParamSet *params = nullptr;
458 int32_t ret = HksInitParamSet(¶ms);
459 if (ret != HKS_SUCCESS) {
460 LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret);
461 return ret;
462 }
463
464 struct HksParam hksParam[] = {
465 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
466 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
467 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
468 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
469 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
470 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
471 };
472
473 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
474 if (ret != HKS_SUCCESS) {
475 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
476 HksFreeParamSet(¶ms);
477 return ret;
478 }
479
480 ret = HksBuildParamSet(¶ms);
481 if (ret != HKS_SUCCESS) {
482 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
483 HksFreeParamSet(¶ms);
484 return ret;
485 }
486
487 ret = HksKeyExist(&rootKeyName, params);
488 HksFreeParamSet(¶ms);
489 if (ret != HKS_SUCCESS) {
490 LOG_ERROR("HksEncrypt failed with error %{public}d", ret);
491 }
492 return ret == HKS_SUCCESS;
493 }
494
InitPath(const std::string & path)495 bool RdbSecurityManager::InitPath(const std::string &path)
496 {
497 constexpr mode_t DEFAULT_UMASK = 0002;
498 if (access(path.c_str(), F_OK) == 0) {
499 return true;
500 }
501 umask(DEFAULT_UMASK);
502 if (mkdir(path.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0 && errno != EEXIST) {
503 LOG_ERROR("mkdir error:%{public}d, dbDir:%{public}s", errno, SqliteUtils::Anonymous(path).c_str());
504 return false;
505 }
506 return true;
507 }
508
LoadSecretKeyFromFile(KeyFileType keyFile)509 RdbPassword RdbSecurityManager::LoadSecretKeyFromFile(KeyFileType keyFile)
510 {
511 std::string keyPath;
512 GetKeyPath(keyFile, keyPath);
513 if (!FileExists(keyPath)) {
514 LOG_ERROR("Key file not exists.");
515 return {};
516 }
517
518 RdbSecretKeyData keyData;
519 if (!LoadSecretKeyFromDisk(keyPath, keyData)) {
520 LOG_ERROR("Load key failed.");
521 return {};
522 }
523
524 std::vector<uint8_t> key;
525 if (!DecryptWorkKey(keyData.secretKey, key)) {
526 LOG_ERROR("Decrypt key failed!");
527 return {};
528 }
529
530 RdbPassword rdbPasswd;
531 rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue);
532 rdbPasswd.SetValue(key.data(), key.size());
533 key.assign(key.size(), 0);
534 return rdbPasswd;
535 }
536
LoadSecretKeyFromDisk(const std::string & keyPath,RdbSecretKeyData & keyData)537 bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData)
538 {
539 LOG_INFO("LoadSecretKeyFromDisk begin.");
540 std::vector<char> content;
541 {
542 std::lock_guard<std::mutex> lock(mutex_);
543 if (!LoadBufferFromFile(keyPath, content) || content.empty()) {
544 LOG_ERROR("LoadBufferFromFile failed!");
545 return false;
546 }
547 }
548
549 std::vector<uint8_t> distribute;
550 auto iter = content.begin();
551 distribute.push_back(*iter);
552 iter++;
553 uint8_t distributeStatus = TransferByteArrayToType<uint8_t>(distribute);
554
555 std::vector<uint8_t> createTime;
556 for (int i = 0; i < static_cast<int>(sizeof(time_t) / sizeof(uint8_t)); i++) {
557 createTime.push_back(*iter);
558 iter++;
559 }
560
561 keyData.distributed = distributeStatus;
562 keyData.timeValue = TransferByteArrayToType<time_t>(createTime);
563 keyData.secretKey.insert(keyData.secretKey.end(), iter, content.end());
564
565 return true;
566 }
567
GetRdbPassword(KeyFileType keyFile)568 RdbPassword RdbSecurityManager::GetRdbPassword(KeyFileType keyFile)
569 {
570 LOG_INFO("GetRdbPassword Begin.");
571 if (!CheckKeyDataFileExists(keyFile)) {
572 if (!SaveSecretKeyToFile(keyFile)) {
573 LOG_ERROR("Failed to save key.");
574 return {};
575 }
576 }
577
578 return LoadSecretKeyFromFile(keyFile);
579 }
580
GenerateRootKeyAlias()581 std::vector<uint8_t> RdbSecurityManager::GenerateRootKeyAlias()
582 {
583 std::vector<uint8_t> rootKeyAlias =
584 std::vector<uint8_t>(RDB_ROOT_KEY_ALIAS_PREFIX, RDB_ROOT_KEY_ALIAS_PREFIX + strlen(RDB_ROOT_KEY_ALIAS_PREFIX));
585 if (!bundleName_.empty()) {
586 rootKeyAlias.insert(rootKeyAlias.end(), bundleName_.begin(), bundleName_.end());
587 } else {
588 rootKeyAlias.insert(rootKeyAlias.end(), dbDir_.begin(), dbDir_.end());
589 }
590
591 return rootKeyAlias;
592 }
593
DelRdbSecretDataFile(const std::string & path)594 void RdbSecurityManager::DelRdbSecretDataFile(const std::string &path)
595 {
596 LOG_INFO("Delete all key files begin.");
597 std::lock_guard<std::mutex> lock(mutex_);
598 ParsePath(path);
599 SqliteUtils::DeleteFile(keyPath_);
600 SqliteUtils::DeleteFile(newKeyPath_);
601 }
602
IsKeyExpired(const time_t & createTime)603 bool RdbSecurityManager::IsKeyExpired(const time_t &createTime)
604 {
605 auto timePoint = std::chrono::system_clock::from_time_t(createTime);
606 return ((timePoint + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now());
607 }
608
GetInstance()609 RdbSecurityManager &RdbSecurityManager::GetInstance()
610 {
611 static RdbSecurityManager instance;
612 return instance;
613 }
614
RemoveSuffix(const std::string & name)615 static std::string RemoveSuffix(const std::string &name)
616 {
617 std::string suffix(".db");
618 auto pos = name.rfind(suffix);
619 if (pos == std::string::npos || pos < name.length() - suffix.length()) {
620 return name;
621 }
622 return { name, 0, pos };
623 }
624
ParsePath(const std::string & path)625 void RdbSecurityManager::ParsePath(const std::string &path)
626 {
627 dbDir_ = ExtractFilePath(path);
628 const std::string dbName = ExtractFileName(path);
629 dbName_ = RemoveSuffix(dbName);
630 dbKeyDir_ = dbDir_ + std::string("key/");
631 keyPath_ = dbKeyDir_ + dbName_ + std::string(RdbSecurityManager::SUFFIX_PUB_KEY);
632 newKeyPath_ = dbKeyDir_ + dbName_ + std::string(RdbSecurityManager::SUFFIX_PUB_KEY_NEW);
633 }
634
CheckKeyDataFileExists(RdbSecurityManager::KeyFileType fileType)635 bool RdbSecurityManager::CheckKeyDataFileExists(RdbSecurityManager::KeyFileType fileType)
636 {
637 if (fileType == KeyFileType::PUB_KEY_FILE) {
638 return FileExists(keyPath_);
639 } else {
640 return FileExists(newKeyPath_);
641 }
642 }
643
GetKeyPath(RdbSecurityManager::KeyFileType keyType,std::string & keyPath)644 void RdbSecurityManager::GetKeyPath(RdbSecurityManager::KeyFileType keyType, std::string &keyPath)
645 {
646 if (keyType == KeyFileType::PUB_KEY_FILE) {
647 keyPath = keyPath_;
648 } else {
649 keyPath = newKeyPath_;
650 }
651 }
652
DelRdbSecretDataFile(RdbSecurityManager::KeyFileType keyFile)653 void RdbSecurityManager::DelRdbSecretDataFile(RdbSecurityManager::KeyFileType keyFile)
654 {
655 std::string keyPath;
656 GetKeyPath(keyFile, keyPath);
657 SqliteUtils::DeleteFile(keyPath);
658 }
659
UpdateKeyFile()660 void RdbSecurityManager::UpdateKeyFile()
661 {
662 if (SqliteUtils::RenameFile(newKeyPath_, keyPath_) != E_OK) {
663 LOG_ERROR("Rename key file failed.");
664 return;
665 }
666 }
667 } // namespace NativeRdb
668 } // namespace OHOS
669