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