From 5a896fb58903ad399a5e590e9ae577594e7c2a29 Mon Sep 17 00:00:00 2001 From: zwtmichael Date: Tue, 20 Sep 2022 21:46:02 +0800 Subject: [PATCH] update sha algo feature Signed-off-by: zwtmichael --- .../storage/src/sqlite/sqlite_utils.cpp | 162 ++++++++++++++---- .../storage/src/sqlite/sqlite_utils.h | 12 +- ...ributeddb_relational_encrypted_db_test.cpp | 14 ++ ...tributeddb_storage_data_operation_test.cpp | 143 ++++++++++++++++ .../distributeddb_storage_encrypt_test.cpp | 2 +- ...ributeddb_relational_ver_p2p_sync_test.cpp | 61 ++++++- ...distributeddb_single_ver_p2p_sync_test.cpp | 144 ++++++++++++++++ 7 files changed, 501 insertions(+), 37 deletions(-) diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index 3a39540e50c..15694733fed 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -57,6 +57,11 @@ namespace { const std::string JSON_EXTRACT_BY_PATH_TEST_CREATED = "SELECT json_extract_by_path('{\"field\":0}', '$.field', 0);"; const std::string DEFAULT_ATTACH_CIPHER = "PRAGMA cipher_default_attach_cipher="; const std::string DEFAULT_ATTACH_KDF_ITER = "PRAGMA cipher_default_attach_kdf_iter=5000"; + const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1;"; + const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;"; + const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;"; + const std::string SHA1_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA1;"; + const std::string SHA256_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA256;"; const std::string EXPORT_BACKUP_SQL = "SELECT export_database('backup');"; const std::string CIPHER_CONFIG_SQL = "PRAGMA codec_cipher="; const std::string KDF_ITER_CONFIG_SQL = "PRAGMA codec_kdf_iter="; @@ -141,7 +146,6 @@ int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&db if (setWal) { sqls.push_back(WAL_MODE_SQL); } - std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri; int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, flag, nullptr); if (errCode != SQLITE_OK) { @@ -150,7 +154,7 @@ int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&db goto END; } - errCode = SetDataBaseProperty(dbTemp, properties, sqls); + errCode = SetDataBaseProperty(dbTemp, properties, setWal, sqls); if (errCode != SQLITE_OK) { LOGE("[SQLite] SetDataBaseProperty failed: %d", errCode); goto END; @@ -432,33 +436,28 @@ int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql) return SQLiteUtils::MapSQLiteErrno(errCode); } -int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool isMemDb, uint32_t iterTimes) +int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes) { if (db == nullptr) { return -E_INVALID_DB; } - // in memory mode no need cipher - if (isMemDb) { - return E_OK; - } - if (passwd.GetSize() != 0) { -#ifndef OMIT_ENCRYPT - int errCode = sqlite3_key(db, static_cast(passwd.GetData()), static_cast(passwd.GetSize())); - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtils][Setkey] config key failed:(%d)", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); + int errCode = SetKeyInner(db, type, passwd, iterTimes); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][Setkey] set keyInner failed:%d", errCode); + return errCode; } - - errCode = SQLiteUtils::SetCipherSettings(db, type, iterTimes); + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL); if (errCode != E_OK) { - LOGE("[SQLiteUtils][Setkey] set cipher settings failed:%d", errCode); + LOGE("[SQLiteUtils][Setkey] set sha algo failed:%d", errCode); + return errCode; + } + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][Setkey] set rekey sha algo failed:%d", errCode); return errCode; } -#else - return -E_NOT_SUPPORT; -#endif } // verify key @@ -471,7 +470,11 @@ int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &pass if (errCode == -E_BUSY) { return errCode; } - return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + errCode = UpdateCipherShaAlgo(db, setWal, type, passwd, iterTimes); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][Setkey] upgrade cipher sha algo failed:%d", errCode); + return errCode; + } } return E_OK; } @@ -509,6 +512,34 @@ int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::str int SQLiteUtils::AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password, const std::string &attachDbAbsPath, const std::string &attachAsName) +{ + int errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode); + return errCode; + } + errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName); + if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) { + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_ATTACH_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha1 algo failed:%d", errCode); + return errCode; + } + errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][AttachNewDatabase] attach db failed:%d", errCode); + return errCode; + } + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode); + } + } + return errCode; +} + +int SQLiteUtils::AttachNewDatabaseInner(sqlite3 *db, CipherType type, const CipherPassword &password, + const std::string &attachDbAbsPath, const std::string &attachAsName) { // example: "ATTACH '../new.db' AS backup KEY XXXX;" std::string attachSql = "ATTACH ? AS " + attachAsName + " KEY ?;"; // Internal interface not need verify alias name @@ -922,12 +953,14 @@ int SQLiteUtils::GetVersion(const OpenDbProperties &properties, int &version) LOGE("Open database failed: %d, sys:%d", errCode, errno); goto END; } - - errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, properties.isMemDb, - properties.iterTimes); - if (errCode != E_OK) { - LOGE("Set key failed: %d", errCode); - goto END; + // in memory mode no need cipher + if (!properties.isMemDb) { + errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, false, + properties.iterTimes); + if (errCode != E_OK) { + LOGE("Set key failed: %d", errCode); + goto END; + } } errCode = GetVersion(dbTemp, version); @@ -1983,7 +2016,7 @@ int SQLiteUtils::ExplainPlan(sqlite3 *db, const std::string &execSql, bool isQue return errCode; } -int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, +int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal, const std::vector &sqls) { // Set the default busy handler to retry automatically before returning SQLITE_BUSY. @@ -1991,12 +2024,13 @@ int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &proper if (errCode != E_OK) { return errCode; } - - errCode = SQLiteUtils::SetKey(db, properties.cipherType, properties.passwd, properties.isMemDb, - properties.iterTimes); - if (errCode != E_OK) { - LOGD("SQLiteUtils::SetKey fail!!![%d]", errCode); - return errCode; + if (!properties.isMemDb) { + errCode = SQLiteUtils::SetKey(db, properties.cipherType, properties.passwd, setWal, + properties.iterTimes); + if (errCode != E_OK) { + LOGD("SQLiteUtils::SetKey fail!!![%d]", errCode); + return errCode; + } } for (const auto &sql : sqls) { @@ -2184,4 +2218,66 @@ void SQLiteUtils::GetSelectCols(sqlite3_stmt *stmt, std::vector &co colNames.emplace_back(name == nullptr ? std::string() : std::string(name)); } } + +int SQLiteUtils::SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword &passwd, uint32_t iterTimes) +{ +#ifndef OMIT_ENCRYPT + int errCode = sqlite3_key(db, static_cast(passwd.GetData()), static_cast(passwd.GetSize())); + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtils][SetKeyInner] config key failed:(%d)", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + errCode = SQLiteUtils::SetCipherSettings(db, type, iterTimes); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][SetKeyInner] set cipher settings failed:%d", errCode); + } + return errCode; +#else + return -E_NOT_SUPPORT; +#endif +} + +int SQLiteUtils::UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, const CipherPassword &passwd, uint32_t iterTimes) +{ + if (passwd.GetSize() != 0) { + int errCode = SetKeyInner(db, type, passwd, iterTimes); + if (errCode != E_OK) { + return errCode; + } + // set sha1 algo for old version + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set sha algo failed:%d", errCode); + return errCode; + } + // try to get user version + errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] verify version failed:%d", errCode); + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + if (errCode == -E_BUSY) { + return errCode; + } + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + } + // try to update sha algo by rekey operation + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set rekey sha algo failed:%d", errCode); + return errCode; + } + if (setWal) { + errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL); + if (errCode != E_OK) { + LOGE("[SQLite][UpdateCipherShaAlgo] execute wal sql failed: %d", errCode); + return errCode; + } + } + return Rekey(db, passwd); + } + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; +} } // namespace DistributedDB \ No newline at end of file diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index f35765b3bc7..3b59e575fed 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -101,7 +101,7 @@ public: static int ExecuteRawSQL(sqlite3 *db, const std::string &sql); - static int SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool isMemDb, + static int SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes = DBConstant::DEFAULT_ITER_TIMES); static int GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value); @@ -156,6 +156,9 @@ public: static int AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password, const std::string &attachDbAbsPath, const std::string &attachAsName = "backup"); + static int AttachNewDatabaseInner(sqlite3 *db, CipherType type, const CipherPassword &password, + const std::string &attachDbAbsPath, const std::string &attachAsName); + static int CreateMetaDatabase(const std::string &metaDbPath); static int CheckIntegrity(sqlite3 *db, const std::string &sql); @@ -200,6 +203,8 @@ public: static void GetSelectCols(sqlite3_stmt *stmt, std::vector &colNames); + static int SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword &passwd, uint32_t iterTimes); + private: static int CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal); @@ -221,7 +226,7 @@ private: static void GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); - static int SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, + static int SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal, const std::vector &sqls); static int RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func); @@ -236,6 +241,9 @@ private: static void SqliteLogCallback(void *data, int err, const char *msg); + static int UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, const CipherPassword &passwd, + uint32_t iterTimes); + static std::mutex logMutex_; static std::string lastErrorMsg_; }; diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp index c8630e358b6..9f20c2eeb6b 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp @@ -151,6 +151,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInC string sql = "PRAGMA key='" + CORRECT_KEY + "';" "PRAGMA codec_kdf_iter=" + std::to_string(DEFAULT_ITER) + ";" + "PRAGMA codec_hmac_algo=SHA256;" + "PRAGMA codec_rekey_hmac_algo=SHA256;" "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); @@ -183,6 +185,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInS string sql = "PRAGMA key='" + CORRECT_KEY + "';" "PRAGMA codec_kdf_iter=" + std::to_string(DEFAULT_ITER) + ";" + "PRAGMA codec_hmac_algo=SHA256;" + "PRAGMA codec_rekey_hmac_algo=SHA256;" "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); @@ -215,6 +219,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithPasswdInSpli string sql = "PRAGMA key='" + CORRECT_KEY + "';" "PRAGMA codec_kdf_iter=" + std::to_string(DEFAULT_ITER) + ";" + "PRAGMA codec_hmac_algo=SHA256;" + "PRAGMA codec_rekey_hmac_algo=SHA256;" "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); @@ -271,6 +277,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithInvalidParam string sql = "PRAGMA key='" + CORRECT_KEY + "';" "PRAGMA codec_kdf_iter=" + std::to_string(DEFAULT_ITER) + ";" + "PRAGMA codec_hmac_algo=SHA256;" + "PRAGMA codec_rekey_hmac_algo=SHA256;" "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); @@ -313,6 +321,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithCustomizedIt string sql = "PRAGMA key='" + CORRECT_KEY + "';" "PRAGMA codec_kdf_iter=" + std::to_string(CUSTOMIZED_ITER) + ";" + "PRAGMA codec_hmac_algo=SHA256;" + "PRAGMA codec_rekey_hmac_algo=SHA256;" "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); @@ -369,6 +379,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi string sql = "PRAGMA key='" + CORRECT_KEY + "';" "PRAGMA codec_kdf_iter=" + std::to_string(CUSTOMIZED_ITER) + ";" + "PRAGMA codec_hmac_algo=SHA256;" + "PRAGMA codec_rekey_hmac_algo=SHA256;" "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); @@ -503,6 +515,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RemoteQueryForEncryptedDb_001, string sql = "PRAGMA key='" + CORRECT_KEY + "';" "PRAGMA codec_kdf_iter=" + std::to_string(DEFAULT_ITER) + ";" + "PRAGMA codec_hmac_algo=SHA256;" + "PRAGMA codec_rekey_hmac_algo=SHA256;" "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp index 832cc32666f..e6c4363754c 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp @@ -31,6 +31,16 @@ using namespace std; namespace { string g_testDir; SQLiteLocalKvDBConnection *g_connection = nullptr; + CipherPassword g_passwd; + CipherPassword g_passwd2; + std::vector g_passwdVect = {'p', 's', 'd', '1'}; + std::vector g_passwdVect2 = {'p', 's', 'd', '2'}; + const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256"; + const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1"; + const std::string USER_VERSION_SQL = "PRAGMA user_version;"; + const std::string SET_USER_VERSION_SQL = "PRAGMA user_version=100;"; + const std::string SHA1_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA1;"; + const std::string SHA256_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA256;"; } class DistributedDBStorageDataOperationTest : public testing::Test { @@ -44,6 +54,8 @@ public: void DistributedDBStorageDataOperationTest::SetUpTestCase(void) { DistributedDBToolsUnitTest::TestDirInit(g_testDir); + g_passwd.SetValue(g_passwdVect.data(), g_passwdVect.size()); + g_passwd2.SetValue(g_passwdVect2.data(), g_passwdVect2.size()); } void DistributedDBStorageDataOperationTest::TearDownTestCase(void) @@ -639,4 +651,135 @@ HWTEST_F(DistributedDBStorageDataOperationTest, CutValueIntoBlock002, TestSize.L CheckSplitData(value2, 0ul, valueDic, savedValue); CheckRecoverData(savedValue, valueDic, value2); EXPECT_EQ(valueDic.size(), 0ul); +} + +/** + * @tc.name: ShaAlgoEncryptTest001 + * @tc.desc: Test sqlite sha algo + * @tc.type: FUNC + * @tc.require: AR000HI2JS + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBStorageDataOperationTest, ShaAlgoEncryptTest001, TestSize.Level1) +{ + sqlite3 *db = nullptr; + /** + * @tc.steps: step1. use sha256 to open db + * * @tc.expected: step1. interface return ok + */ + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/ShaAlgoEncryptTest001.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + EXPECT_EQ(SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, g_passwd, DBConstant::DEFAULT_ITER_TIMES), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL), E_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, SET_USER_VERSION_SQL) == E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL), E_OK); + /** + * @tc.steps: step2. close db + * * @tc.expected: step2. interface return ok + */ + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step1. use sha1 to open db + * * @tc.expected: step1. interface return not ok + */ + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + EXPECT_EQ(SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, g_passwd, DBConstant::DEFAULT_ITER_TIMES), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL), -E_INVALID_PASSWD_OR_CORRUPTED_DB); + sqlite3_close_v2(db); +} + +/** + * @tc.name: ShaAlgoEncryptTest002 + * @tc.desc: Test sqlite sha algo in attach mode + * @tc.type: FUNC + * @tc.require: AR000HI2JS + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBStorageDataOperationTest, ShaAlgoEncryptTest002, TestSize.Level1) +{ + sqlite3 *db = nullptr; + /** + * @tc.steps: step1. use sha256 to open db + * * @tc.expected: step1. interface return ok + */ + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/ShaAlgoEncryptTest002_attach.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + EXPECT_EQ(SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, g_passwd, DBConstant::DEFAULT_ITER_TIMES), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL), E_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, SET_USER_VERSION_SQL) == E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL), E_OK); + /** + * @tc.steps: step2. close db + * * @tc.expected: step2. interface return ok + */ + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step3. open new db and attach old db + * * @tc.expected: step3. interface return ok + */ + std::string fileUrl2 = g_testDir + "/ShaAlgoEncryptTest002.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl2.c_str(), &db, flag, nullptr), SQLITE_OK); + EXPECT_EQ(SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, g_passwd2, DBConstant::DEFAULT_ITER_TIMES), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL), E_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, SET_USER_VERSION_SQL) == E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL), E_OK); + std::string attachName = "EncryptTest002"; + EXPECT_EQ(SQLiteUtils::AttachNewDatabaseInner(db, CipherType::AES_256_GCM, g_passwd, fileUrl, attachName), E_OK); + /** + * @tc.steps: step4. close db + * * @tc.expected: step4. interface return ok + */ + sqlite3_close_v2(db); +} + +/** + * @tc.name: ShaAlgoEncryptTest003 + * @tc.desc: Test sqlite sha algo in attach mode + * @tc.type: FUNC + * @tc.require: AR000HI2JS + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBStorageDataOperationTest, ShaAlgoEncryptTest003, TestSize.Level1) +{ + sqlite3 *db = nullptr; + /** + * @tc.steps: step1. use sha256 to open db + * * @tc.expected: step1. interface return ok + */ + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/ShaAlgoEncryptTest003_attach.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + EXPECT_EQ(SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, g_passwd, DBConstant::DEFAULT_ITER_TIMES), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL), E_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, SET_USER_VERSION_SQL) == E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL), E_OK); + /** + * @tc.steps: step2. close db + * * @tc.expected: step2. interface return ok + */ + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step3. open new db and attach old db + * * @tc.expected: step3. interface return ok + */ + std::string fileUrl2 = g_testDir + "/ShaAlgoEncryptTest003.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl2.c_str(), &db, flag, nullptr), SQLITE_OK); + EXPECT_EQ(SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, g_passwd2, DBConstant::DEFAULT_ITER_TIMES), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL), E_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, SET_USER_VERSION_SQL) == E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL), E_OK); + std::string attachName = "EncryptTest003"; + EXPECT_EQ(SQLiteUtils::AttachNewDatabase(db, CipherType::AES_256_GCM, g_passwd, fileUrl, attachName), E_OK); + /** + * @tc.steps: step4. close db + * * @tc.expected: step4. interface return ok + */ + sqlite3_close_v2(db); } \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_encrypt_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_encrypt_test.cpp index ca927e8b6c1..e1733785e15 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_encrypt_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_encrypt_test.cpp @@ -1348,7 +1348,7 @@ HWTEST_F(DistributedDBStorageEncryptTest, EncryptTest025, TestSize.Level1) * @tc.expected: step6. Return SQLITE_OK. */ Value valueGet; - GetValue(KEY_1, valueGet); + EXPECT_EQ(GetValue(KEY_1, valueGet), SQLITE_OK); EXPECT_EQ(valueGet, VALUE_1); /** diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index d2b6ecea96b..890d2013895 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -55,6 +55,9 @@ namespace { const char DEFAULT_CHAR = 'D'; const std::string DEFAULT_TEXT = "This is a text"; const std::vector DEFAULT_BLOB(ONE_HUNDERED, DEFAULT_CHAR); + const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1"; + const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256"; + const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256"; RelationalStoreManager g_mgr(APP_ID, USER_ID); std::string g_testDir; @@ -95,7 +98,7 @@ namespace { ASSERT_TRUE(g_rdbDelegatePtr != nullptr); } - int GetDB(sqlite3 *&db) + int GetDB(sqlite3 *&db, bool isSha256Algo = true) { int flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; const auto &dbPath = g_dbDir; @@ -108,6 +111,12 @@ namespace { "PRAGMA key='" + (g_isAfterRekey ? REKEY_KEY : CORRECT_KEY) + "';" "PRAGMA codec_kdf_iter=" + std::to_string(DEFAULT_ITER) + ";"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + if (isSha256Algo) { + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL), E_OK); + } else { + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL), E_OK); + } + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL), E_OK); #endif EXPECT_EQ(SQLiteUtils::RegisterCalcHash(db), E_OK); EXPECT_EQ(SQLiteUtils::RegisterGetSysTime(db), E_OK); @@ -1932,4 +1941,54 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, OrderbyWriteTimeSync001, TestSiz EXPECT_EQ(g_rdbDelegatePtr->Sync({DEVICE_B}, DistributedDB::SYNC_MODE_PUSH_ONLY, query, nullptr, false), NOT_SUPPORT); } + +/** +* @tc.name: EncryptedAlgoUpgrade001 + * @tc.desc: Test upgrade encrypted db can sync normally + * @tc.type: FUNC + * @tc.require: AR000HI2JS + * @tc.author: zhuwentao +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSize.Level0) +{ + if (g_rdbDelegatePtr != nullptr) { + LOGD("CloseStore Start"); + ASSERT_EQ(g_mgr.CloseStore(g_rdbDelegatePtr), OK); + g_rdbDelegatePtr = nullptr; + } + EXPECT_EQ(OS::RemoveFile(g_dbDir), E_OK); + /** + * @tc.steps: step1. open old db use sha1 algo and insert some data + * @tc.expected: step1. interface return ok + */ + sqlite3 *db = nullptr; + EXPECT_EQ(GetDB(db, false), SQLITE_OK); + const std::string user_version_sql = "PRAGMA user_version=101;"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, user_version_sql), E_OK); + sqlite3_close(db); + + /** + * @tc.steps: step2. open db by OpenStore + * @tc.expected: step2. interface return ok + */ + OpenStore(); + /** + * @tc.steps: step3. sync with push + * @tc.expected: step3. interface return ok + */ + std::map dataMap; + PrepareEnvironment(dataMap, {g_deviceB}); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); + CheckVirtualData(dataMap); + dataMap.clear(); + + /** + * @tc.steps: step4. sync with pull + * @tc.expected: step4. interface return ok + */ + + Query query = Query::Select(g_tableName); + g_deviceB->GenericVirtualDevice::Sync(DistributedDB::SYNC_MODE_PULL_ONLY, query, true); + CheckVirtualData(dataMap); +} #endif \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp index 21ac5c0a518..cb1b9de8de0 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp @@ -18,6 +18,7 @@ #include #include "db_constant.h" +#include "db_common.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "kv_store_nb_delegate.h" @@ -40,6 +41,16 @@ namespace { const std::string DEVICE_A = "real_device"; const std::string DEVICE_B = "deviceB"; const std::string DEVICE_C = "deviceC"; + const std::string CREATE_SYNC_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS sync_data(" \ + "key BLOB NOT NULL," \ + "value BLOB," \ + "timestamp INT NOT NULL," \ + "flag INT NOT NULL," \ + "device BLOB," \ + "ori_device BLOB," \ + "hash_key BLOB PRIMARY KEY NOT NULL," \ + "w_timestamp INT);"; KvStoreDelegateManager g_mgr(APP_ID, USER_ID); KvStoreConfig g_config; @@ -53,6 +64,65 @@ namespace { // the type of g_kvDelegateCallback is function auto g_kvDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, placeholders::_1, placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvDelegatePtr)); + + void PullSyncTest() + { + DBStatus status = OK; + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + + Key key = {'1'}; + Key key2 = {'2'}; + Value value = {'1'}; + g_deviceB->PutData(key, value, 0, 0); + g_deviceB->PutData(key2, value, 1, 0); + + std::map result; + status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + ASSERT_TRUE(status == OK); + + ASSERT_TRUE(result.size() == devices.size()); + for (const auto &pair : result) { + LOGD("dev %s, status %d", pair.first.c_str(), pair.second); + EXPECT_TRUE(pair.second == OK); + } + Value value3; + EXPECT_EQ(g_kvDelegatePtr->Get(key, value3), OK); + EXPECT_EQ(value3, value); + EXPECT_EQ(g_kvDelegatePtr->Get(key2, value3), OK); + EXPECT_EQ(value3, value); + } + + void CrudTest() + { + vector entries; + int totalSize = 10; + for (int i = 0; i < totalSize; i++) { + Entry entry; + entry.key.push_back(i); + entry.value.push_back('2'); + entries.push_back(entry); + } + EXPECT_TRUE(g_kvDelegatePtr->PutBatch(entries) == OK); + for (const auto &entry : entries) { + Value resultvalue; + EXPECT_TRUE(g_kvDelegatePtr->Get(entry.key, resultvalue) == OK); + EXPECT_TRUE(resultvalue == entry.value); + } + for (int i = 0; i < totalSize / 2; i++) { + g_kvDelegatePtr->Delete(entries[i].key); + Value resultvalue; + EXPECT_TRUE(g_kvDelegatePtr->Get(entries[i].key, resultvalue) == NOT_FOUND); + } + for (int i = totalSize / 2; i < totalSize; i++) { + Value value = entries[i].value; + value.push_back('x'); + EXPECT_TRUE(g_kvDelegatePtr->Put(entries[i].key, value) == OK); + Value resultvalue; + EXPECT_TRUE(g_kvDelegatePtr->Get(entries[i].key, resultvalue) == OK); + EXPECT_TRUE(resultvalue == value); + } + } } class DistributedDBSingleVerP2PSyncTest : public testing::Test { @@ -2530,3 +2600,77 @@ HWTEST_F(DistributedDBSingleVerP2PSyncTest, OrderbyWriteTimeSync001, TestSize.Le Query query = Query::Select().PrefixKey({'k'}).OrderByWriteTime(true); EXPECT_EQ(g_kvDelegatePtr->Sync(devices, DistributedDB::SYNC_MODE_PUSH_ONLY, nullptr, query, true), NOT_SUPPORT); } + +/** + * @tc.name: EncryptedAlgoUpgrade001 + * @tc.desc: Test upgrade encrypted db can sync normally + * @tc.type: FUNC + * @tc.require: AR000HI2JS + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBSingleVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSize.Level3) +{ + /** + * @tc.steps: step1. clear db + * * @tc.expected: step1. interface return ok + */ + if (g_kvDelegatePtr != nullptr) { + ASSERT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK); + g_kvDelegatePtr = nullptr; + DBStatus status = g_mgr.DeleteKvStore(STORE_ID); + LOGD("delete kv store status %d", status); + ASSERT_TRUE(status == OK); + } + + CipherPassword passwd; + std::vector passwdVect = {'p', 's', 'd', '1'}; + passwd.SetValue(passwdVect.data(), passwdVect.size()); + /** + * @tc.steps: step2. open old db by sql + * * @tc.expected: step2. interface return ok + */ + std::string identifier = DBCommon::GenerateIdentifierId(STORE_ID, APP_ID, USER_ID); + std::string hashDir = DBCommon::TransferHashString(identifier); + std::string hexHashDir = DBCommon::TransferStringToHex(hashDir); + std::string dbPath = g_testDir + "/" + hexHashDir + "/single_ver"; + ASSERT_TRUE(DBCommon::CreateDirectory(g_testDir + "/" + hexHashDir) == OK); + ASSERT_TRUE(DBCommon::CreateDirectory(dbPath) == OK); + std::vector dbDir {DBConstant::MAINDB_DIR, DBConstant::METADB_DIR, DBConstant::CACHEDB_DIR}; + for (const auto &item : dbDir) { + ASSERT_TRUE(DBCommon::CreateDirectory(dbPath + "/" + item) == OK); + } + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + sqlite3 *db; + std::string fileUrl = dbPath + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + ".db"; + ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr) == SQLITE_OK); + SQLiteUtils::SetKeyInner(db, CipherType::AES_256_GCM, passwd, DBConstant::DEFAULT_ITER_TIMES); + /** + * @tc.steps: step3. create table and close + * * @tc.expected: step3. interface return ok + */ + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, CREATE_SYNC_TABLE_SQL) == E_OK); + sqlite3_close_v2(db); + db = nullptr; + LOGI("create old db success"); + /** + * @tc.steps: step4. get kvstore + * * @tc.expected: step4. interface return ok + */ + KvStoreNbDelegate::Option option; + option.isEncryptedDb = true; + option.cipher = CipherType::AES_256_GCM; + option.passwd = passwd; + g_mgr.GetKvStore(STORE_ID, option, g_kvDelegateCallback); + ASSERT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvDelegatePtr != nullptr); + /** + * @tc.steps: step5. sync ok + * * @tc.expected: step5. interface return ok + */ + PullSyncTest(); + /** + * @tc.steps: step5. crud ok + * * @tc.expected: step5. interface return ok + */ + CrudTest(); +} -- Gitee