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