Improve DB::Crypto code coverage 12/238412/2
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 7 Jul 2020 07:14:35 +0000 (09:14 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 14 Jul 2020 16:26:39 +0000 (18:26 +0200)
Change-Id: I0fcb65833641ef75ab2af3c265e15df4d45231b6

unit-tests/DBFixture.cpp
unit-tests/DBFixture.h
unit-tests/test_db_crypto.cpp

index da73dfe..3f8c3cc 100644 (file)
@@ -185,6 +185,16 @@ DB::Row DBFixture::create_default_row(const Name &name,
        return row;
 }
 
+DB::Row DBFixture::create_default_binary_row()
+{
+       DB::Row row = create_default_row(m_default_name, m_default_owner, DataType::BINARY_DATA);
+       row.data = RawBuffer(100, 20);
+       row.dataSize = row.data.size();
+       row.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
+
+       return row;
+}
+
 void DBFixture::compare_row(const DB::Row &lhs, const DB::Row &rhs)
 {
        BOOST_CHECK_MESSAGE(lhs.name == rhs.name,
index fd2381c..fb036b6 100644 (file)
@@ -45,6 +45,7 @@ public:
        static CKM::DB::Row create_default_row(const CKM::Name &name,
                                                                                   const CKM::ClientId &owner,
                                                                                   CKM::DataType type = CKM::DataType::BINARY_DATA);
+       static CKM::DB::Row create_default_binary_row();
        static void compare_row(const CKM::DB::Row &lhs, const CKM::DB::Row &rhs);
 
        // ::::::::::::::::::::::::: time measurement :::::::::::::::::::::::::
index 5ed8d5e..1317561 100644 (file)
@@ -41,6 +41,17 @@ const unsigned int c_num_names = 500;
 const unsigned int c_num_names_add_test = 5000;
 const unsigned int c_names_per_owner = 15;
 
+void addRow(DB::RowVector& rows, DataType::Type type)
+{
+       DB::Row row = DBFixture::create_default_row(DBFixture::m_default_name,
+                                                   DBFixture::m_default_owner,
+                                                   type);
+       row.data = RawBuffer(100, 20);
+       row.dataSize = row.data.size();
+       row.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
+       rows.push_back(std::move(row));
+};
+
 } // namespace anonymous
 
 BOOST_FIXTURE_TEST_SUITE(DBCRYPTO_TEST, DBFixture)
@@ -109,6 +120,266 @@ POSITIVE_TEST_CASE(DBtestBackend)
        check_DB_integrity(rowPattern);
 }
 
+POSITIVE_TEST_CASE(DBtestMove)
+{
+       struct TestCrypto : public DB::Crypto {
+               explicit TestCrypto(DB::Crypto orig) : DB::Crypto(std::move(orig)) {}
+
+               bool empty() const { return !m_connection; }
+       };
+
+       TestCrypto tmp(std::move(m_db));
+       BOOST_REQUIRE(!tmp.empty());
+
+       BOOST_REQUIRE_NO_THROW(tmp = std::move(tmp));
+       BOOST_REQUIRE(!tmp.empty());
+
+       m_db = std::move(tmp);
+       BOOST_REQUIRE(tmp.empty());
+}
+
+POSITIVE_TEST_CASE(DBtestSaveRows)
+{
+       DB::RowVector rows;
+
+       addRow(rows, DataType::KEY_RSA_PRIVATE);
+       addRow(rows, DataType::KEY_RSA_PUBLIC);
+       addRow(rows, DataType::CERTIFICATE);
+       addRow(rows, DataType::CHAIN_CERT_0);
+       addRow(rows, DataType::CHAIN_CERT_1);
+       addRow(rows, DataType::CHAIN_CERT_2);
+
+       BOOST_REQUIRE_NO_THROW(m_db.saveRows(m_default_name, m_default_owner, rows));
+
+       BOOST_REQUIRE(m_db.isNameOwnerPresent(m_default_name, m_default_owner));
+
+       rows.clear();
+       BOOST_REQUIRE_NO_THROW(m_db.getRows(m_default_name,
+                                           m_default_owner,
+                                           DataType::KEY_RSA_PUBLIC,
+                                           DataType::KEY_RSA_PRIVATE,
+                                           rows));
+       BOOST_REQUIRE(rows.size() == 2);
+       BOOST_REQUIRE(rows[0].dataType.isKey() && rows[1].dataType.isKey());
+
+       rows.clear();
+       BOOST_REQUIRE_NO_THROW(m_db.getRows(m_default_name,
+                                           m_default_owner,
+                                           DataType::KEY_DSA_PRIVATE,
+                                           rows));
+       BOOST_REQUIRE(rows.empty());
+}
+
+NEGATIVE_TEST_CASE(DBtestSaveRowsDuplicated)
+{
+       DB::RowVector rows;
+
+       addRow(rows, DataType::KEY_RSA_PRIVATE);
+       addRow(rows, DataType::KEY_RSA_PUBLIC);
+       addRow(rows, DataType::CERTIFICATE);
+       addRow(rows, DataType::CHAIN_CERT_0);
+       addRow(rows, DataType::CHAIN_CERT_1);
+       addRow(rows, DataType::CHAIN_CERT_1);
+
+       // duplicated type
+       DB::Crypto::Transaction transaction(&m_db);
+       BOOST_REQUIRE_THROW(m_db.saveRows(m_default_name, m_default_owner, rows),
+                           Exc::DatabaseFailed);
+       transaction.rollback();
+
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(m_default_name, m_default_owner));
+}
+
+NEGATIVE_TEST_CASE(DBtestSaveRowsEmpty)
+{
+       BOOST_REQUIRE_NO_THROW(m_db.saveRows(m_default_name, m_default_owner, DB::RowVector()));
+
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(m_default_name, m_default_owner));
+}
+
+NEGATIVE_TEST_CASE(DBtestSaveRowDuplicated)
+{
+       DB::Row row = create_default_binary_row();
+
+       BOOST_REQUIRE_NO_THROW(m_db.saveRow(row));
+       BOOST_REQUIRE_THROW(m_db.saveRow(row), Exc::DatabaseFailed);
+}
+
+NEGATIVE_TEST_CASE(DBtestGetRowsNonExisting)
+{
+       DB::RowVector rows;
+       BOOST_REQUIRE_NO_THROW(m_db.getRows(m_default_name,
+                                           m_default_owner,
+                                           DataType::DB_FIRST,
+                                           DataType::DB_LAST,
+                                           rows));
+       BOOST_REQUIRE(rows.empty());
+}
+
+POSITIVE_TEST_CASE(DBtestUpdateRow)
+{
+       DB::Row row = create_default_binary_row();
+
+       BOOST_REQUIRE_NO_THROW(m_db.saveRow(row));
+
+       row.dataSize--;
+       row.data.resize(row.dataSize);
+       BOOST_REQUIRE_NO_THROW(m_db.updateRow(row));
+
+       DB::Crypto::RowOptional rowOpt;
+       BOOST_REQUIRE_NO_THROW(rowOpt = m_db.getRow(row.name, row.owner, DataType::BINARY_DATA));
+       BOOST_REQUIRE(rowOpt);
+       BOOST_REQUIRE(rowOpt->dataSize == row.dataSize);
+       BOOST_REQUIRE(rowOpt->data == row.data);
+}
+
+NEGATIVE_TEST_CASE(DBtestUpdateRowNotExisting)
+{
+       DB::Row row = create_default_binary_row();
+       BOOST_REQUIRE_NO_THROW(m_db.updateRow(row));
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(row.name, row.owner));
+
+       BOOST_REQUIRE_NO_THROW(m_db.saveRow(row));
+
+       row.name = "non-existent name";
+       BOOST_REQUIRE_NO_THROW(m_db.updateRow(row));
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(row.name, row.owner));
+}
+
+POSITIVE_TEST_CASE(DBtestDeleteRow)
+{
+       DB::Row row = create_default_binary_row();
+       BOOST_REQUIRE_NO_THROW(m_db.saveRow(row));
+       BOOST_REQUIRE(m_db.isNameOwnerPresent(row.name, row.owner));
+       BOOST_REQUIRE(m_db.deleteRow(row.name, row.owner));
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(row.name, row.owner));
+}
+
+NEGATIVE_TEST_CASE(DBtestDeleteRowNotExisting)
+{
+       DB::Row row = create_default_binary_row();
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(row.name, row.owner));
+       BOOST_REQUIRE(!m_db.deleteRow(row.name, row.owner));
+}
+
+POSITIVE_TEST_CASE(DBtestIsNameOwnerPresent)
+{
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(m_default_name, m_default_owner));
+
+       insert_row(m_default_name, m_default_owner);
+
+       BOOST_REQUIRE(m_db.isNameOwnerPresent(m_default_name, m_default_owner));
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent("non-existent name", m_default_owner));
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(m_default_name, "non-existent owner"));
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent("non-existent name", "non-existent owner"));
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent("", ""));
+
+       delete_row(m_default_name, m_default_owner);
+
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(m_default_name, m_default_owner));
+}
+
+NEGATIVE_TEST_CASE(DBtestIsNameOwnerPresentSqlInjectionAttempt)
+{
+       insert_row(m_default_name, m_default_owner);
+
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent("name'; DROP TABLE NAMES; --", m_default_owner));
+       BOOST_REQUIRE(!m_db.isNameOwnerPresent(m_default_name, "owner'; DROP TABLE NAMES; --"));
+       BOOST_REQUIRE(m_db.isNameOwnerPresent(m_default_name, m_default_owner));
+}
+
+POSITIVE_TEST_CASE(DBtestPermissions)
+{
+       constexpr char OTHER_OWNER[] = "other owner";
+       insert_row(m_default_name, m_default_owner);
+
+       auto checkPermission = [&](const char* accessor, PermissionMask perm)
+       {
+               PermissionMaskOptional maskOpt;
+               BOOST_REQUIRE_NO_THROW(maskOpt = m_db.getPermissionRow(m_default_name,
+                                                                      m_default_owner,
+                                                                      accessor));
+               BOOST_REQUIRE(!!maskOpt == (perm != Permission::NONE));
+               if (perm != Permission::NONE)
+                       BOOST_REQUIRE(*maskOpt == perm);
+
+       };
+
+       checkPermission(m_default_owner, Permission::READ | Permission::REMOVE);
+
+       checkPermission(OTHER_OWNER, Permission::NONE);
+
+       BOOST_REQUIRE_NO_THROW(m_db.setPermission(m_default_name,
+                                                 m_default_owner,
+                                                 OTHER_OWNER,
+                                                 Permission::READ));
+
+       checkPermission(OTHER_OWNER, Permission::READ);
+
+       BOOST_REQUIRE_NO_THROW(m_db.setPermission(m_default_name,
+                                                 m_default_owner,
+                                                 OTHER_OWNER,
+                                                 Permission::NONE));
+
+       checkPermission(OTHER_OWNER, Permission::NONE);
+}
+
+NEGATIVE_TEST_CASE(DBtestPermissionsNonExisting)
+{
+       PermissionMaskOptional maskOpt;
+       BOOST_REQUIRE_NO_THROW(maskOpt = m_db.getPermissionRow(m_default_name,
+                                                                                                                  m_default_owner,
+                                                                                                                  m_default_owner));
+       BOOST_REQUIRE(!maskOpt);
+}
+
+POSITIVE_TEST_CASE(DBtestClientKey)
+{
+       DB::Crypto::RawBufferOptional keyOpt;
+       RawBuffer key = createRandom(16);
+
+       BOOST_REQUIRE_NO_THROW(keyOpt = m_db.getKey(m_default_owner));
+       BOOST_REQUIRE(!keyOpt);
+
+       BOOST_REQUIRE_NO_THROW(m_db.saveKey(m_default_owner, key));
+
+       BOOST_REQUIRE_NO_THROW(keyOpt = m_db.getKey(m_default_owner));
+       BOOST_REQUIRE(keyOpt);
+       BOOST_REQUIRE(*keyOpt == key);
+
+       constexpr size_t NAME_CNT = 4;
+       constexpr const char* NAMES[NAME_CNT] = { "name1", "name2", "name3", "name4" };
+       for (auto name : NAMES)
+               insert_row(name, m_default_owner);
+
+       OwnerNameVector ownerNameVector;
+       BOOST_REQUIRE_NO_THROW(m_db.listNames(m_default_owner, ownerNameVector, DataType::BINARY_DATA));
+       BOOST_REQUIRE(ownerNameVector.size() == NAME_CNT);
+
+       BOOST_REQUIRE_NO_THROW(m_db.deleteKey(m_default_owner));
+
+       ownerNameVector.clear();
+       BOOST_REQUIRE_NO_THROW(m_db.listNames(m_default_owner, ownerNameVector, DataType::BINARY_DATA));
+       BOOST_REQUIRE(ownerNameVector.empty());
+
+       BOOST_REQUIRE_NO_THROW(keyOpt = m_db.getKey(m_default_owner));
+       BOOST_REQUIRE(!keyOpt);
+}
+
+NEGATIVE_TEST_CASE(DBtestClientKey)
+{
+       DB::Crypto::RawBufferOptional keyOpt;
+       RawBuffer key = createRandom(16);
+
+       BOOST_REQUIRE_NO_THROW(m_db.deleteKey(m_default_owner));
+
+       BOOST_REQUIRE_NO_THROW(keyOpt = m_db.getKey(m_default_owner));
+       BOOST_REQUIRE(!keyOpt);
+
+       BOOST_REQUIRE_NO_THROW(m_db.saveKey(m_default_owner, key));
+       BOOST_REQUIRE_THROW(m_db.saveKey(m_default_owner, key), Exc::DatabaseFailed);
+}
+
 BOOST_AUTO_TEST_SUITE_END()