• 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 #include "store_factory.h"
16 
17 #include <cerrno>
18 #include <cstdio>
19 #include <gtest/gtest.h>
20 #include <sys/types.h>
21 #include <vector>
22 
23 #include "backup_manager.h"
24 #include "file_ex.h"
25 #include "hks_api.h"
26 #include "hks_param.h"
27 #include "security_manager.h"
28 #include "store_manager.h"
29 #include "store_util.h"
30 #include "sys/stat.h"
31 #include "types.h"
32 namespace {
33 using namespace testing::ext;
34 using namespace OHOS::DistributedKv;
35 
36 static StoreId storeId = { "single_test" };
37 static AppId appId = { "rekey" };
38 static Options options = {
39     .encrypt = true,
40     .securityLevel = S1,
41     .area = EL1,
42     .kvStoreType = SINGLE_VERSION,
43     .baseDir = "/data/service/el1/public/database/rekey",
44 };
45 static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key";
46 static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client";
47 
48 class StoreFactoryTest : public testing::Test {
49 public:
50     using DBStore = DistributedDB::KvStoreNbDelegate;
51     using DBManager = DistributedDB::KvStoreDelegateManager;
52     using DBOption = DistributedDB::KvStoreNbDelegate::Option;
53     using DBPassword = SecurityManager::DBPassword;
54     using DBStatus = DistributedDB::DBStatus;
55 
56     static constexpr int OUTDATED_TIME = (24 * 500);
57     static constexpr int NOT_OUTDATED_TIME = (24 * 50);
58 
59     static void SetUpTestCase(void);
60     static void TearDownTestCase(void);
61     void SetUp();
62     void TearDown();
63 
64     std::chrono::system_clock::time_point GetDate(const std::string &name, const std::string &path);
65     bool ChangeKeyDate(const std::string &name, const std::string &path, int duration, const std::vector<uint8_t> &key);
66     bool MoveToRekeyPath(Options options, StoreId storeId);
67     std::shared_ptr<StoreFactoryTest::DBManager> GetDBManager(const std::string &path, const AppId &appId);
68     DBOption GetOption(const Options &options, const DBPassword &dbPassword);
69     DBStatus ChangeKVStoreDate(const std::string &storeId, std::shared_ptr<DBManager> dbManager, const Options &options,
70         DBPassword &dbPassword, int time);
71     bool ModifyDate(int time);
72     bool Encrypt(const std::vector<uint8_t> &key, SecurityManager::SecurityContent &content);
73     bool Decrypt(const SecurityManager::SecurityContent &content, std::vector<uint8_t> &key);
74     static void DeleteKVStore();
75 
76     static std::vector<uint8_t> vecRootKeyAlias_;
77     static std::vector<uint8_t> vecAad_;
78 };
79 
80 std::vector<uint8_t> StoreFactoryTest::vecRootKeyAlias_ =
81     std::vector<uint8_t>(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS));
82 std::vector<uint8_t> StoreFactoryTest::vecAad_ =
83     std::vector<uint8_t>(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD));
84 
SetUpTestCase(void)85 void StoreFactoryTest::SetUpTestCase(void) { }
86 
TearDownTestCase(void)87 void StoreFactoryTest::TearDownTestCase(void) { }
88 
SetUp(void)89 void StoreFactoryTest::SetUp(void)
90 {
91     std::string baseDir = "/data/service/el1/public/database/rekey";
92     mkdir(baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH));
93 }
94 
TearDown(void)95 void StoreFactoryTest::TearDown(void)
96 {
97     DeleteKVStore();
98     (void)remove("/data/service/el1/public/database/rekey");
99 }
100 
DeleteKVStore()101 void StoreFactoryTest::DeleteKVStore()
102 {
103     StoreManager::GetInstance().Delete(appId, storeId, options.baseDir);
104 }
105 
Encrypt(const std::vector<uint8_t> & key,SecurityManager::SecurityContent & content)106 bool StoreFactoryTest::Encrypt(const std::vector<uint8_t> &key, SecurityManager::SecurityContent &content)
107 {
108     struct HksParamSet *params = nullptr;
109     int32_t ret = HksInitParamSet(&params);
110     if (ret != HKS_SUCCESS) {
111         return false;
112     }
113 
114     uint8_t nonceValue[SecurityManager::SecurityContent::NONCE_SIZE] = {0};
115     struct HksBlob blobNonce = { .size = SecurityManager::SecurityContent::NONCE_SIZE, .data = nonceValue };
116     ret = HksGenerateRandom(nullptr, &blobNonce);
117     if (ret != HKS_SUCCESS) {
118         return false;
119     }
120 
121     struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() };
122     struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() };
123     struct HksBlob plainKey = { uint32_t(key.size()), const_cast<uint8_t *>(key.data()) };
124     struct HksParam hksParam[] = {
125         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
126         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT },
127         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
128         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
129         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
130         { .tag = HKS_TAG_NONCE, .blob = blobNonce },
131         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
132         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
133     };
134     ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
135     if (ret != HKS_SUCCESS) {
136         HksFreeParamSet(&params);
137         return false;
138     }
139 
140     ret = HksBuildParamSet(&params);
141     if (ret != HKS_SUCCESS) {
142         HksFreeParamSet(&params);
143         return false;
144     }
145 
146     uint8_t cipherBuf[256] = { 0 };
147     struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf };
148     ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText);
149     (void)HksFreeParamSet(&params);
150     if (ret != HKS_SUCCESS) {
151         return false;
152     }
153     std::vector<uint8_t> nonceContent(blobNonce.data, blobNonce.data + blobNonce.size);
154     content.nonceValue = nonceContent;
155     std::vector<uint8_t> encryptValue(cipherText.data, cipherText.data + cipherText.size);
156     content.encryptValue = encryptValue;
157     std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0);
158     return true;
159 }
160 
Decrypt(const SecurityManager::SecurityContent & content,std::vector<uint8_t> & key)161 bool StoreFactoryTest::Decrypt(const SecurityManager::SecurityContent &content, std::vector<uint8_t> &key)
162 {
163     struct HksParamSet *params = nullptr;
164     int32_t ret = HksInitParamSet(&params);
165     if (ret != HKS_SUCCESS) {
166         return false;
167     }
168 
169     struct HksBlob blobNonce = { .size = uint32_t(content.nonceValue.size()),
170         .data = const_cast<uint8_t*>(&(content.nonceValue[0])) };
171     struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) };
172     struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) };
173     struct HksBlob encryptedKeyBlob = { uint32_t(content.encryptValue.size()),
174         const_cast<uint8_t *>(content.encryptValue.data()) };
175     struct HksParam hksParam[] = {
176         { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES },
177         { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT },
178         { .tag = HKS_TAG_DIGEST, .uint32Param = 0 },
179         { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM },
180         { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE },
181         { .tag = HKS_TAG_NONCE, .blob = blobNonce },
182         { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad },
183         { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE },
184     };
185     ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0]));
186     if (ret != HKS_SUCCESS) {
187         HksFreeParamSet(&params);
188         return false;
189     }
190 
191     ret = HksBuildParamSet(&params);
192     if (ret != HKS_SUCCESS) {
193         HksFreeParamSet(&params);
194         return false;
195     }
196 
197     uint8_t plainBuf[256] = { 0 };
198     struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf };
199     ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob);
200     (void)HksFreeParamSet(&params);
201     if (ret != HKS_SUCCESS) {
202         return false;
203     }
204 
205     key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size);
206     std::fill(plainBuf, plainBuf + sizeof(plainBuf), 0);
207     return true;
208 }
209 
GetDate(const std::string & name,const std::string & path)210 std::chrono::system_clock::time_point StoreFactoryTest::GetDate(const std::string &name, const std::string &path)
211 {
212     std::chrono::system_clock::time_point timePoint;
213     auto keyPath = path + "/key/" + name + ".key_v1";
214     if (!OHOS::FileExists(keyPath)) {
215         return timePoint;
216     }
217     std::vector<char> content;
218     auto loaded = OHOS::LoadBufferFromFile(keyPath, content);
219     if (!loaded) {
220         return timePoint;
221     }
222     SecurityManager::SecurityContent securityContent;
223     size_t offset = SecurityManager::SecurityContent::MAGIC_NUM;
224     securityContent.nonceValue.assign(content.begin() + offset,
225         content.begin() + offset + SecurityManager::SecurityContent::NONCE_SIZE);
226     offset += SecurityManager::SecurityContent::NONCE_SIZE;
227     securityContent.encryptValue.assign(content.begin() + offset, content.end());
228     std::vector<uint8_t> fullKey;
229     if (!Decrypt(securityContent, fullKey)) {
230         return timePoint;
231     }
232     offset = 0;
233     securityContent.version = fullKey[offset++];
234     securityContent.time.assign(fullKey.begin() + offset,
235         fullKey.begin() + offset + (sizeof(time_t) / sizeof(uint8_t)));
236     timePoint = std::chrono::system_clock::from_time_t(
237         *reinterpret_cast<time_t *>(const_cast<uint8_t *>(securityContent.time.data())));
238     return timePoint;
239 }
240 
ChangeKeyDate(const std::string & name,const std::string & path,int duration,const std::vector<uint8_t> & key)241 bool StoreFactoryTest::ChangeKeyDate(const std::string &name, const std::string &path, int duration,
242     const std::vector<uint8_t> &key)
243 {
244     auto keyPath = path + "/key/" + name + ".key_v1";
245     if (!OHOS::FileExists(keyPath)) {
246         return false;
247     }
248     SecurityManager::SecurityContent securityContent;
249     securityContent.version = SecurityManager::SecurityContent::CURRENT_VERSION;
250     auto time = std::chrono::system_clock::to_time_t(
251         std::chrono::system_clock::system_clock::now() - std::chrono::hours(duration));
252     securityContent.time = { reinterpret_cast<uint8_t *>(&time), reinterpret_cast<uint8_t *>(&time) + sizeof(time) };
253     std::vector<uint8_t> keyContent;
254     keyContent.push_back(securityContent.version);
255     keyContent.insert(keyContent.end(), securityContent.time.begin(), securityContent.time.end());
256     keyContent.insert(keyContent.end(), key.begin(), key.end());
257     if (!Encrypt(keyContent, securityContent)) {
258         return false;
259     }
260     std::vector<char> content;
261     for (size_t index = 0; index < SecurityManager::SecurityContent::MAGIC_NUM; ++index) {
262         content.push_back(char(SecurityManager::SecurityContent::MAGIC_CHAR));
263     }
264     content.insert(content.end(), securityContent.nonceValue.begin(), securityContent.nonceValue.end());
265     content.insert(content.end(), securityContent.encryptValue.begin(), securityContent.encryptValue.end());
266     return OHOS::SaveBufferToFile(keyPath, content);
267 }
268 
MoveToRekeyPath(Options options,StoreId storeId)269 bool StoreFactoryTest::MoveToRekeyPath(Options options, StoreId storeId)
270 {
271     std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1";
272     std::string rekeyFileName = options.baseDir + "/rekey/key/" + storeId.storeId + ".new.key_v1";
273     bool result = StoreUtil::Rename(keyFileName, rekeyFileName);
274     if (!result) {
275         return false;
276     }
277     result = StoreUtil::Remove(keyFileName);
278     return result;
279 }
280 
GetDBManager(const std::string & path,const AppId & appId)281 std::shared_ptr<StoreFactoryTest::DBManager> StoreFactoryTest::GetDBManager(const std::string &path, const AppId &appId)
282 {
283     std::string fullPath = path + "/kvdb";
284     StoreUtil::InitPath(fullPath);
285     std::shared_ptr<DBManager> dbManager = std::make_shared<DBManager>(appId.appId, "default");
286     dbManager->SetKvStoreConfig({ fullPath });
287     BackupManager::GetInstance().Init(path);
288     return dbManager;
289 }
290 
GetOption(const Options & options,const DBPassword & dbPassword)291 StoreFactoryTest::DBOption StoreFactoryTest::GetOption(const Options &options, const DBPassword &dbPassword)
292 {
293     DBOption dbOption;
294     dbOption.syncDualTupleMode = true; // tuple of (appid+storeid)
295     dbOption.createIfNecessary = options.createIfMissing;
296     dbOption.isNeedRmCorruptedDb = options.rebuild;
297     dbOption.isMemoryDb = (!options.persistent);
298     dbOption.isEncryptedDb = options.encrypt;
299     if (options.encrypt) {
300         dbOption.cipher = DistributedDB::CipherType::AES_256_GCM;
301         dbOption.passwd = dbPassword.password;
302     }
303 
304     dbOption.conflictResolvePolicy = options.kvStoreType == KvStoreType::SINGLE_VERSION ?
305         DistributedDB::LAST_WIN :
306         DistributedDB::DEVICE_COLLABORATION;
307 
308     dbOption.schema = options.schema;
309     dbOption.createDirByStoreIdOnly = true;
310     dbOption.secOption = StoreUtil::GetDBSecurity(options.securityLevel);
311     return dbOption;
312 }
313 
ChangeKVStoreDate(const std::string & storeId,std::shared_ptr<DBManager> dbManager,const Options & options,DBPassword & dbPassword,int time)314 StoreFactoryTest::DBStatus StoreFactoryTest::ChangeKVStoreDate(const std::string &storeId,
315     std::shared_ptr<DBManager> dbManager, const Options &options, DBPassword &dbPassword, int time)
316 {
317     DBStatus status;
318     const auto dbOption = GetOption(options, dbPassword);
319     DBStore *store = nullptr;
320     dbManager->GetKvStore(storeId, dbOption, [&status, &store](auto dbStatus, auto *dbStore) {
321         status = dbStatus;
322         store = dbStore;
323     });
324     dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, options.baseDir, false);
325     std::vector<uint8_t> key(dbPassword.GetData(), dbPassword.GetData() + dbPassword.GetSize());
326     if (!ChangeKeyDate(storeId, options.baseDir, time, key)) {
327         std::cout << "failed" << std::endl;
328     }
329     dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, options.baseDir, false);
330     auto dbStatus = store->Rekey(dbPassword.password);
331     dbManager->CloseKvStore(store);
332     return dbStatus;
333 }
334 
ModifyDate(int time)335 bool StoreFactoryTest::ModifyDate(int time)
336 {
337     auto dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, options.baseDir, false);
338     auto dbManager = GetDBManager(options.baseDir, appId);
339     auto dbstatus = ChangeKVStoreDate(storeId, dbManager, options, dbPassword, time);
340     return StoreUtil::ConvertStatus(dbstatus) == SUCCESS;
341 }
342 
343 /**
344  * @tc.name: Rekey
345  * @tc.desc: test rekey function
346  * @tc.type: FUNC
347  * @tc.require:
348  * @tc.author: Cui Renjie
349  */
350 HWTEST_F(StoreFactoryTest, Rekey, TestSize.Level1)
351 {
352     Status status = DB_ERROR;
353     options.autoRekey = true;
354     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
355     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
356     ASSERT_EQ(status, SUCCESS);
357 
358     ASSERT_TRUE(ModifyDate(OUTDATED_TIME));
359 
360     auto oldKeyTime = GetDate(storeId, options.baseDir);
361     ASSERT_FALSE(std::chrono::system_clock::now() - oldKeyTime < std::chrono::seconds(2));
362 
363     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
364     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
365     ASSERT_EQ(status, SUCCESS);
366 
367     auto newKeyTime = GetDate(storeId, options.baseDir);
368     ASSERT_TRUE(std::chrono::system_clock::now() - newKeyTime < std::chrono::seconds(2));
369 }
370 
371 /**
372  * @tc.name: RekeyNotOutdated
373  * @tc.desc: try to rekey kvstore with not outdated password
374  * @tc.type: FUNC
375  * @tc.require:
376  * @tc.author: Cui Renjie
377  */
378 HWTEST_F(StoreFactoryTest, RekeyNotOutdated, TestSize.Level1)
379 {
380     Status status = DB_ERROR;
381     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
382     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
383     ASSERT_EQ(status, SUCCESS);
384 
385     ASSERT_TRUE(ModifyDate(NOT_OUTDATED_TIME));
386     auto oldKeyTime = GetDate(storeId, options.baseDir);
387 
388     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
389     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
390     ASSERT_EQ(status, SUCCESS);
391 
392     auto newKeyTime = GetDate(storeId, options.baseDir);
393     ASSERT_EQ(oldKeyTime, newKeyTime);
394 }
395 
396 /**
397  * @tc.name: RekeyInterrupted0
398  * @tc.desc: mock the situation that open store after rekey was interrupted last time,
399  *           which caused key file lost but rekey key file exist.
400  * @tc.type: FUNC
401  * @tc.require:
402  * @tc.author: Cui Renjie
403  */
404 HWTEST_F(StoreFactoryTest, RekeyInterruptedWhileChangeKeyFile, TestSize.Level1)
405 {
406     Status status = DB_ERROR;
407     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
408     ASSERT_EQ(status, SUCCESS);
409     auto oldKeyTime = GetDate(storeId, options.baseDir);
410 
411     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
412     ASSERT_EQ(status, SUCCESS);
413     ASSERT_TRUE(MoveToRekeyPath(options, storeId));
414 
415     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
416     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
417     ASSERT_EQ(status, SUCCESS);
418     std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1";
419     auto isKeyExist = StoreUtil::IsFileExist(keyFileName);
420     ASSERT_TRUE(isKeyExist);
421 
422     auto newKeyTime = GetDate(storeId, options.baseDir);
423     ASSERT_TRUE(newKeyTime - oldKeyTime < std::chrono::seconds(2));
424 }
425 
426 /**
427  * @tc.name: RekeyInterrupted1
428  * @tc.desc: mock the situation that open store after rekey was interrupted last time,
429  *           which caused key file not changed but rekey key file exist.
430  * @tc.type: FUNC
431  * @tc.require:
432  * @tc.author: Cui Renjie
433  */
434 HWTEST_F(StoreFactoryTest, RekeyInterruptedBeforeChangeKeyFile, TestSize.Level1)
435 {
436     Status status = DB_ERROR;
437     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
438     ASSERT_EQ(status, SUCCESS);
439     auto oldKeyTime = GetDate(storeId, options.baseDir);
440 
441     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
442     ASSERT_EQ(status, SUCCESS);
443     ASSERT_EQ(MoveToRekeyPath(options, storeId), true);
444 
445     StoreId newStoreId = { "newStore" };
446     StoreManager::GetInstance().GetKVStore(appId, newStoreId, options, status);
447 
448     std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1";
449     std::string mockKeyFileName = options.baseDir + "/key/" + newStoreId.storeId + ".key_v1";
450     StoreUtil::Rename(mockKeyFileName, keyFileName);
451     StoreUtil::Remove(mockKeyFileName);
452     auto isKeyExist = StoreUtil::IsFileExist(mockKeyFileName);
453     ASSERT_FALSE(isKeyExist);
454     isKeyExist = StoreUtil::IsFileExist(keyFileName);
455     ASSERT_TRUE(isKeyExist);
456 
457     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
458     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
459     ASSERT_EQ(status, SUCCESS);
460 
461     isKeyExist = StoreUtil::IsFileExist(keyFileName);
462     ASSERT_TRUE(isKeyExist);
463 
464     auto newKeyTime = GetDate(storeId, options.baseDir);
465     ASSERT_TRUE(newKeyTime - oldKeyTime < std::chrono::seconds(2));
466 }
467 
468 /**
469  * @tc.name: RekeyNoPwdFile
470  * @tc.desc: try to open kvstore and execute RekeyRecover() without key and rekey key files.
471  * @tc.type: FUNC
472  * @tc.require:
473  * @tc.author: Cui Renjie
474  */
475 HWTEST_F(StoreFactoryTest, RekeyNoPwdFile, TestSize.Level1)
476 {
477     Status status = DB_ERROR;
478     options.autoRekey = false;
479     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
480     ASSERT_EQ(status, SUCCESS);
481 
482     status = StoreManager::GetInstance().CloseKVStore(appId, storeId);
483     ASSERT_EQ(status, SUCCESS);
484     std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1";
485     StoreUtil::Remove(keyFileName);
486 
487     auto isKeyExist = StoreUtil::IsFileExist(keyFileName);
488     ASSERT_EQ(isKeyExist, false);
489 
490     StoreManager::GetInstance().GetKVStore(appId, storeId, options, status);
491     ASSERT_EQ(status, SUCCESS);
492 
493     isKeyExist = StoreUtil::IsFileExist(keyFileName);
494     ASSERT_EQ(isKeyExist, true);
495 }
496 } // namespace