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
RdbSecurityManager()203 RdbSecurityManager::RdbSecurityManager()
204 : nonce_(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)),
205 aad_(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)){};
206
207 RdbSecurityManager::~RdbSecurityManager() = default;
208
GenerateRandomNum(int32_t len)209 std::vector<uint8_t> RdbSecurityManager::GenerateRandomNum(int32_t len)
210 {
211 std::random_device randomDevice;
212 std::uniform_int_distribution<int> distribution(0, std::numeric_limits<uint8_t>::max());
213 std::vector<uint8_t> key(len);
214 for (int32_t i = 0; i < len; i++) {
215 key[i] = static_cast<uint8_t>(distribution(randomDevice));
216 }
217 return key;
218 }
219
SaveSecretKeyToFile(const std::string & dbPath,RdbSecurityManager::KeyFileType keyFileType)220 bool RdbSecurityManager::SaveSecretKeyToFile(const std::string &dbPath, RdbSecurityManager::KeyFileType keyFileType)
221 {
222 LOG_INFO("SaveSecretKeyToFile begin.");
223 if (!HasRootKey()) {
224 LOG_ERROR("Root key not exists!");
225 return false;
226 }
227 std::vector<uint8_t> key = GenerateRandomNum(RDB_KEY_SIZE);
228 RdbSecretKeyData keyData;
229 keyData.timeValue = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now());
230 keyData.distributed = 0;
231 keyData.secretKey = EncryptWorkKey(key);
232
233 if (keyData.secretKey.empty()) {
234 LOG_ERROR("Key size is 0");
235 key.assign(key.size(), 0);
236 return false;
237 }
238
239 key.assign(key.size(), 0);
240 if (!RdbSecurityManager::InitPath(ExtractFilePath(dbPath) + std::string("key/"))) {
241 LOG_ERROR("InitPath err.");
242 return false;
243 }
244
245 return SaveSecretKeyToDisk(GetKeyPath(dbPath, keyFileType), keyData);
246 }
247
SaveSecretKeyToDisk(const std::string & keyPath,RdbSecretKeyData & keyData)248 bool RdbSecurityManager::SaveSecretKeyToDisk(const std::string &keyPath, RdbSecretKeyData &keyData)
249 {
250 LOG_INFO("SaveSecretKeyToDisk begin.");
251
252 std::vector<uint8_t> distributedInByte = { &keyData.distributed, &keyData.distributed + sizeof(uint8_t) };
253 std::vector<uint8_t> timeInByte = { reinterpret_cast<uint8_t *>(&keyData.timeValue),
254 reinterpret_cast<uint8_t *>(&keyData.timeValue) + sizeof(time_t) };
255
256 std::vector<char> secretKeyInChar;
257 secretKeyInChar.insert(secretKeyInChar.end(), distributedInByte.begin(), distributedInByte.end());
258 secretKeyInChar.insert(secretKeyInChar.end(), timeInByte.begin(), timeInByte.end());
259 secretKeyInChar.insert(secretKeyInChar.end(), keyData.secretKey.begin(), keyData.secretKey.end());
260
261 std::lock_guard<std::mutex> lock(mutex_);
262 bool ret = SaveBufferToFile(keyPath, secretKeyInChar);
263 if (!ret) {
264 LOG_ERROR("SaveBufferToFile failed!");
265 return false;
266 }
267
268 return true;
269 }
270
GenerateRootKey(const std::vector<uint8_t> & rootKeyAlias)271 int RdbSecurityManager::GenerateRootKey(const std::vector<uint8_t> &rootKeyAlias)
272 {
273 LOG_INFO("RDB GenerateRootKey begin.");
274 std::vector<uint8_t> tempRootKeyAlias = rootKeyAlias;
275 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), tempRootKeyAlias.data() };
276 struct HksParamSet *params = nullptr;
277 int32_t ret = HksInitParamSet(¶ms);
278 if (ret != HKS_SUCCESS) {
279 LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret);
280 return ret;
281 }
282
283 struct HksParam hksParam[] = {
284 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
285 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
286 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
287 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
288 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
289 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
290 };
291
292 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
293 if (ret != HKS_SUCCESS) {
294 LOG_ERROR("HksAddParams-client failed with error %{public}d", ret);
295 HksFreeParamSet(¶ms);
296 return ret;
297 }
298
299 ret = HksBuildParamSet(¶ms);
300 if (ret != HKS_SUCCESS) {
301 LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret);
302 HksFreeParamSet(¶ms);
303 return ret;
304 }
305
306 ret = HksGenerateKey(&rootKeyName, params, nullptr);
307 HksFreeParamSet(¶ms);
308 if (ret != HKS_SUCCESS) {
309 LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret);
310 }
311 return ret;
312 }
313
EncryptWorkKey(const std::vector<uint8_t> & key)314 std::vector<uint8_t> RdbSecurityManager::EncryptWorkKey(const std::vector<uint8_t> &key)
315 {
316 struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() };
317 struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() };
318 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), rootKeyAlias_.data() };
319 struct HksBlob plainKey = { uint32_t(key.size()), const_cast<uint8_t *>(key.data()) };
320 struct HksParamSet *params = nullptr;
321 int32_t ret = HksInitParamSet(¶ms);
322 if (ret != HKS_SUCCESS) {
323 LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret);
324 return {};
325 }
326 struct HksParam hksParam[] = {
327 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
328 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
329 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
330 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
331 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
332 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
333 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
334 };
335 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
336 if (ret != HKS_SUCCESS) {
337 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
338 HksFreeParamSet(¶ms);
339 return {};
340 }
341
342 ret = HksBuildParamSet(¶ms);
343 if (ret != HKS_SUCCESS) {
344 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
345 HksFreeParamSet(¶ms);
346 return {};
347 }
348
349 uint8_t cipherBuf[256] = { 0 };
350 struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf };
351 ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText);
352 (void)HksFreeParamSet(¶ms);
353 if (ret != HKS_SUCCESS) {
354 LOG_ERROR("HksEncrypt failed with error %{public}d", ret);
355 return {};
356 }
357
358 std::vector<uint8_t> encryptedKey(cipherText.data, cipherText.data + cipherText.size);
359 (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf));
360
361 return encryptedKey;
362 }
363
DecryptWorkKey(std::vector<uint8_t> & source,std::vector<uint8_t> & key)364 bool RdbSecurityManager::DecryptWorkKey(std::vector<uint8_t> &source, std::vector<uint8_t> &key)
365 {
366 uint8_t aead_[AEAD_LEN] = { 0 };
367 struct HksBlob blobAad = { uint32_t(aad_.size()), &(aad_[0]) };
368 struct HksBlob blobNonce = { uint32_t(nonce_.size()), &(nonce_[0]) };
369 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias_.size()), &(rootKeyAlias_[0]) };
370 struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() };
371 struct HksBlob blobAead = { AEAD_LEN, aead_ };
372
373 struct HksParamSet *params = nullptr;
374 int32_t ret = HksInitParamSet(¶ms);
375 if (ret != HKS_SUCCESS) {
376 LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret);
377 return false;
378 }
379 struct HksParam hksParam[] = {
380 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
381 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
382 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
383 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
384 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
385 { .tag = HKS_TAG_NONCE, .blob = blobNonce },
386 { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
387 { .tag = HKS_TAG_AE_TAG, .blob = blobAead },
388 };
389 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
390 if (ret != HKS_SUCCESS) {
391 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
392 HksFreeParamSet(¶ms);
393 return false;
394 }
395
396 ret = HksBuildParamSet(¶ms);
397 if (ret != HKS_SUCCESS) {
398 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
399 HksFreeParamSet(¶ms);
400 return false;
401 }
402
403 encryptedKeyBlob.size -= AEAD_LEN;
404 for (uint32_t i = 0; i < params->paramsCnt; i++) {
405 if (params->params[i].tag == HKS_TAG_AE_TAG) {
406 uint8_t *tempPtr = encryptedKeyBlob.data;
407 if (memcpy_s(params->params[i].blob.data, AEAD_LEN, tempPtr + encryptedKeyBlob.size, AEAD_LEN) != 0) {
408 LOG_ERROR("Method memcpy_s failed");
409 HksFreeParamSet(¶ms);
410 return false;
411 }
412 break;
413 }
414 }
415
416 uint8_t plainBuf[256] = { 0 };
417 struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf };
418 ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob);
419 (void)HksFreeParamSet(¶ms);
420 if (ret != HKS_SUCCESS) {
421 LOG_ERROR("HksDecrypt failed with error %{public}d", ret);
422 return false;
423 }
424
425 key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size);
426 (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf));
427 return true;
428 }
429
Init(const std::string & bundleName)430 int32_t RdbSecurityManager::Init(const std::string &bundleName)
431 {
432 std::vector<uint8_t> rootKeyAlias = GenerateRootKeyAlias(bundleName);
433 constexpr uint32_t RETRY_MAX_TIMES = 5;
434 constexpr int RETRY_TIME_INTERVAL_MILLISECOND = 1 * 1000 * 1000;
435 int32_t ret = HKS_FAILURE;
436 uint32_t retryCount = 0;
437 while (retryCount < RETRY_MAX_TIMES) {
438 ret = CheckRootKeyExists(rootKeyAlias);
439 if (ret == HKS_ERROR_NOT_EXIST) {
440 hasRootKey_ = false;
441 ret = GenerateRootKey(rootKeyAlias);
442 }
443 if (ret == HKS_SUCCESS) {
444 if (!HasRootKey()) {
445 hasRootKey_ = true;
446 rootKeyAlias_ = std::move(rootKeyAlias);
447 }
448 break;
449 }
450 retryCount++;
451 if (ret != HKS_SUCCESS) {
452 usleep(RETRY_TIME_INTERVAL_MILLISECOND);
453 }
454 }
455 LOG_INFO("retry:%{public}u, error:%{public}d", retryCount, ret);
456 return ret;
457 }
458
CheckRootKeyExists(std::vector<uint8_t> & rootKeyAlias)459 int32_t RdbSecurityManager::CheckRootKeyExists(std::vector<uint8_t> &rootKeyAlias)
460 {
461 LOG_DEBUG("RDB checkRootKeyExist begin.");
462 struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() };
463 struct HksParamSet *params = nullptr;
464 int32_t ret = HksInitParamSet(¶ms);
465 if (ret != HKS_SUCCESS) {
466 LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret);
467 return ret;
468 }
469
470 struct HksParam hksParam[] = {
471 { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
472 { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 },
473 { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT },
474 { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
475 { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
476 { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
477 };
478
479 ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
480 if (ret != HKS_SUCCESS) {
481 LOG_ERROR("HksAddParams failed with error %{public}d", ret);
482 HksFreeParamSet(¶ms);
483 return ret;
484 }
485
486 ret = HksBuildParamSet(¶ms);
487 if (ret != HKS_SUCCESS) {
488 LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
489 HksFreeParamSet(¶ms);
490 return ret;
491 }
492
493 ret = HksKeyExist(&rootKeyName, params);
494 HksFreeParamSet(¶ms);
495 return ret;
496 }
497
InitPath(const std::string & dbKeyDir)498 bool RdbSecurityManager::InitPath(const std::string &dbKeyDir)
499 {
500 constexpr mode_t DEFAULT_UMASK = 0002;
501 if (access(dbKeyDir.c_str(), F_OK) == 0) {
502 return true;
503 }
504 umask(DEFAULT_UMASK);
505 if (mkdir(dbKeyDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0 && errno != EEXIST) {
506 LOG_ERROR("mkdir error:%{public}d, dbDir:%{public}s", errno, SqliteUtils::Anonymous(dbKeyDir).c_str());
507 return false;
508 }
509 return true;
510 }
511
LoadSecretKeyFromFile(const std::string & dbPath,KeyFileType keyFileType)512 RdbPassword RdbSecurityManager::LoadSecretKeyFromFile(const std::string &dbPath, KeyFileType keyFileType)
513 {
514 std::string keyPath = GetKeyPath(dbPath, keyFileType);
515 if (!FileExists(keyPath)) {
516 LOG_ERROR("Key file not exists.");
517 return {};
518 }
519
520 RdbSecretKeyData keyData;
521 if (!LoadSecretKeyFromDisk(keyPath, keyData)) {
522 LOG_ERROR("Load key failed.");
523 return {};
524 }
525
526 std::vector<uint8_t> key;
527 if (!DecryptWorkKey(keyData.secretKey, key)) {
528 LOG_ERROR("Decrypt key failed!");
529 return {};
530 }
531
532 RdbPassword rdbPasswd;
533 rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue);
534 rdbPasswd.SetValue(key.data(), key.size());
535 key.assign(key.size(), 0);
536 return rdbPasswd;
537 }
538
LoadSecretKeyFromDisk(const std::string & keyPath,RdbSecretKeyData & keyData)539 bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData)
540 {
541 LOG_DEBUG("LoadSecretKeyFromDisk begin.");
542 std::vector<char> content;
543 {
544 std::lock_guard<std::mutex> lock(mutex_);
545 if (!LoadBufferFromFile(keyPath, content) || content.empty()) {
546 LOG_ERROR("LoadBufferFromFile failed!");
547 return false;
548 }
549 }
550
551 auto iter = content.begin();
552 keyData.distributed = *iter;
553 iter++;
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 if (createTime.size() == sizeof(time_t)) {
562 keyData.timeValue = *reinterpret_cast<time_t *>(&createTime[0]);
563 }
564
565 keyData.secretKey.insert(keyData.secretKey.end(), iter, content.end());
566
567 return true;
568 }
569
GetRdbPassword(const std::string & dbPath,RdbSecurityManager::KeyFileType keyFileType)570 RdbPassword RdbSecurityManager::GetRdbPassword(const std::string &dbPath, RdbSecurityManager::KeyFileType keyFileType)
571 {
572 if (!IsKeyFileExists(dbPath, keyFileType)) {
573 if (!SaveSecretKeyToFile(dbPath, keyFileType)) {
574 LOG_ERROR("Failed to save key.");
575 return {};
576 }
577 }
578
579 return LoadSecretKeyFromFile(dbPath, keyFileType);
580 }
581
GenerateRootKeyAlias(const std::string & bundlename)582 std::vector<uint8_t> RdbSecurityManager::GenerateRootKeyAlias(const std::string &bundlename)
583 {
584 std::vector<uint8_t> rootKeyAlias =
585 std::vector<uint8_t>(RDB_ROOT_KEY_ALIAS_PREFIX, RDB_ROOT_KEY_ALIAS_PREFIX + strlen(RDB_ROOT_KEY_ALIAS_PREFIX));
586 rootKeyAlias.insert(rootKeyAlias.end(), bundlename.begin(), bundlename.end());
587 return rootKeyAlias;
588 }
589
DelRdbSecretDataFile(const std::string & dbPath)590 void RdbSecurityManager::DelRdbSecretDataFile(const std::string &dbPath)
591 {
592 LOG_INFO("Delete all key files begin.");
593 std::lock_guard<std::mutex> lock(mutex_);
594 auto keyPaths = ConcatenateKeyPath(dbPath);
595 SqliteUtils::DeleteFile(keyPaths.first);
596 SqliteUtils::DeleteFile(keyPaths.second);
597 }
598
IsKeyExpired(const time_t & createTime)599 bool RdbSecurityManager::IsKeyExpired(const time_t &createTime)
600 {
601 auto timePoint = std::chrono::system_clock::from_time_t(createTime);
602 return ((timePoint + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now());
603 }
604
GetInstance()605 RdbSecurityManager &RdbSecurityManager::GetInstance()
606 {
607 static RdbSecurityManager instance;
608 return instance;
609 }
610
RemoveSuffix(const std::string & name)611 static std::string RemoveSuffix(const std::string &name)
612 {
613 std::string suffix(".db");
614 auto pos = name.rfind(suffix);
615 if (pos == std::string::npos || pos < name.length() - suffix.length()) {
616 return name;
617 }
618 return { name, 0, pos };
619 }
620
ConcatenateKeyPath(const std::string & dbPath)621 std::pair<std::string, std::string> RdbSecurityManager::ConcatenateKeyPath(const std::string &dbPath)
622 {
623 const std::string dbName = RemoveSuffix(ExtractFileName(dbPath));
624 const std::string dbKeyDir = ExtractFilePath(dbPath) + "key/";
625 const std::string keyPath = dbKeyDir + dbName + RdbSecurityManager::SUFFIX_PUB_KEY;
626 const std::string newKeyPath = dbKeyDir + dbName + RdbSecurityManager::SUFFIX_PUB_KEY_NEW;
627 return std::make_pair(keyPath, newKeyPath);
628 }
629
IsKeyFileExists(const std::string & dbPath,RdbSecurityManager::KeyFileType keyFileType)630 bool RdbSecurityManager::IsKeyFileExists(const std::string &dbPath, RdbSecurityManager::KeyFileType keyFileType)
631 {
632 return FileExists(GetKeyPath(dbPath, keyFileType));
633 }
634
GetKeyPath(const std::string & dbPath,RdbSecurityManager::KeyFileType keyFileType)635 std::string RdbSecurityManager::GetKeyPath(const std::string &dbPath, RdbSecurityManager::KeyFileType keyFileType)
636 {
637 auto keyPaths = ConcatenateKeyPath(dbPath);
638 if (keyFileType == KeyFileType::PUB_KEY_FILE) {
639 return keyPaths.first;
640 } else {
641 return keyPaths.second;
642 }
643 }
644
DelRdbSecretDataFile(const std::string & dbPath,RdbSecurityManager::KeyFileType keyFileType)645 void RdbSecurityManager::DelRdbSecretDataFile(const std::string &dbPath, RdbSecurityManager::KeyFileType keyFileType)
646 {
647 std::string keyPath = GetKeyPath(dbPath, keyFileType);
648 SqliteUtils::DeleteFile(keyPath);
649 }
650
UpdateKeyFile(const std::string & dbPath)651 void RdbSecurityManager::UpdateKeyFile(const std::string &dbPath)
652 {
653 auto keyPaths = ConcatenateKeyPath(dbPath);
654 if (SqliteUtils::RenameFile(keyPaths.second, keyPaths.first) != E_OK) {
655 LOG_ERROR("Rename key file failed.");
656 return;
657 }
658 }
659
HasRootKey()660 bool RdbSecurityManager::HasRootKey()
661 {
662 return hasRootKey_;
663 }
664 } // namespace NativeRdb
665 } // namespace OHOS
666