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