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