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