• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params);
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(&params);
296         return ret;
297     }
298 
299     ret = HksBuildParamSet(&params);
300     if (ret != HKS_SUCCESS) {
301         LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret);
302         HksFreeParamSet(&params);
303         return ret;
304     }
305 
306     ret = HksGenerateKey(&rootKeyName, params, nullptr);
307     HksFreeParamSet(&params);
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(&params);
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(&params);
339         return {};
340     }
341 
342     ret = HksBuildParamSet(&params);
343     if (ret != HKS_SUCCESS) {
344         LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
345         HksFreeParamSet(&params);
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(&params);
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(&params);
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(&params);
393         return false;
394     }
395 
396     ret = HksBuildParamSet(&params);
397     if (ret != HKS_SUCCESS) {
398         LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
399         HksFreeParamSet(&params);
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(&params);
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(&params);
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(&params);
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(&params);
483         return ret;
484     }
485 
486     ret = HksBuildParamSet(&params);
487     if (ret != HKS_SUCCESS) {
488         LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret);
489         HksFreeParamSet(&params);
490         return ret;
491     }
492 
493     ret = HksKeyExist(&rootKeyName, params);
494     HksFreeParamSet(&params);
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