Improve CryptoLogic tests code coverage 75/228975/4
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 26 Mar 2020 20:10:05 +0000 (21:10 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Mon, 30 Mar 2020 12:01:25 +0000 (14:01 +0200)
Change-Id: I14d50f0269166931e7d4b9a7591c8186eff7d16a

src/manager/service/crypto-logic.cpp
src/manager/service/crypto-logic.h
tests/test_crypto-logic.cpp

index d15a37c..6de54dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014 - 2020 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -53,20 +53,6 @@ const static int AES_GCM_TAG_SIZE = 16;
 
 CryptoLogic::CryptoLogic() {}
 
-CryptoLogic::CryptoLogic(CryptoLogic &&second)
-{
-       m_keyMap = std::move(second.m_keyMap);
-}
-
-CryptoLogic &CryptoLogic::operator=(CryptoLogic &&second)
-{
-       if (this == &second)
-               return *this;
-
-       m_keyMap = std::move(second.m_keyMap);
-       return *this;
-}
-
 bool CryptoLogic::haveKey(const ClientId &client)
 {
        return (m_keyMap.count(client) > 0);
index 154b1b2..75cad96 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014 - 2020 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -32,8 +32,8 @@ class CryptoLogic {
 public:
        CryptoLogic();
        CryptoLogic(const CryptoLogic &second) = delete;
-       CryptoLogic(CryptoLogic &&second);
-       CryptoLogic &operator=(CryptoLogic &&second);
+       CryptoLogic(CryptoLogic &&second) = default;
+       CryptoLogic &operator=(CryptoLogic &&second) = default;
        CryptoLogic &operator=(const CryptoLogic &second) = delete;
 
        virtual ~CryptoLogic() {}
index 142489a..84bed8b 100644 (file)
@@ -17,6 +17,7 @@
 #include <platform/decider.h>
 #include <generic-backend/gstore.h>
 #include <db-row.h>
+#include <base64.h>
 
 #include <utility>
 #include <cstdlib>
@@ -29,15 +30,25 @@ using namespace CKM;
 
 namespace {
 
-Password createRandomPass(size_t size)
+constexpr char TEST_CLIENT[] = "test_client";
+constexpr char TEST_NAME[] = "test_name";
+const auto TEST_KEY = createRandom(32);
+const auto TEST_DATA = createRandom(10);
+
+void changeBase64(RawBuffer& data)
 {
-       static unsigned int seed = ::time(nullptr);
+       auto b64 = [](auto&& coder, RawBuffer& data){
+               coder.append(data);
+               coder.finalize();
+               data = coder.get();
+
+               BOOST_REQUIRE(!data.empty());
+       };
+       b64(Base64Decoder(), data);
 
-       Password buf(size, 0x00);
-       for (size_t i = 0; i < size; ++i)
-               buf[i] = static_cast<Password::value_type>(::rand_r(&seed) % 256);
+       ++data[0];
 
-       return buf;
+       b64(Base64Encoder(), data);
 }
 
 } // namespace anonymous
@@ -48,108 +59,195 @@ POSITIVE_TEST_CASE(move_semantics)
 {
        CryptoLogic logic;
 
-       const ClientId client = "test_client";
-       BOOST_REQUIRE_NO_THROW(logic.pushKey(client, createRandom(10)));
+       BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
 
        CryptoLogic moved(std::move(logic));
-       BOOST_REQUIRE(!logic.haveKey(client));
-       BOOST_REQUIRE(moved.haveKey(client));
+       BOOST_REQUIRE(!logic.haveKey(TEST_CLIENT));
+       BOOST_REQUIRE(moved.haveKey(TEST_CLIENT));
 
        CryptoLogic moveAssigned = std::move(moved);
-       BOOST_REQUIRE(!moved.haveKey(client));
-       BOOST_REQUIRE(moveAssigned.haveKey(client));
+       BOOST_REQUIRE(!moved.haveKey(TEST_CLIENT));
+       BOOST_REQUIRE(moveAssigned.haveKey(TEST_CLIENT));
+}
 
-       moveAssigned = std::move(moveAssigned);
-       BOOST_REQUIRE(moveAssigned.haveKey(client));
+POSITIVE_TEST_CASE(push_have_remove_key)
+{
+       CryptoLogic logic;
+
+       char client[] = "duck";
+       for (size_t i = 0; i < 20; ++i) {
+               ++client[0];
+               BOOST_REQUIRE(!logic.haveKey(client));
+               BOOST_REQUIRE_NO_THROW(logic.pushKey(client, TEST_KEY));
+               BOOST_REQUIRE(logic.haveKey(client));
+               BOOST_REQUIRE_NO_THROW(logic.removeKey(client));
+               BOOST_REQUIRE(!logic.haveKey(client));
+       }
 }
 
-POSITIVE_TEST_CASE(push_key)
+NEGATIVE_TEST_CASE(have_remove_nonexistent_key)
 {
        CryptoLogic logic;
 
-       const ClientId client = "test_client";
+       BOOST_REQUIRE(!logic.haveKey(TEST_CLIENT));
+       BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
+}
 
-       BOOST_REQUIRE_NO_THROW(logic.pushKey(client, createRandom(10)));
+NEGATIVE_TEST_CASE(have_remove_empty)
+{
+       CryptoLogic logic;
 
-       ClientId increasingOwner = "a";
-       for (size_t i = 0; i < 20; ++i, increasingOwner.push_back('a')) {
-               BOOST_REQUIRE_NO_THROW(logic.pushKey(increasingOwner, createRandom(10)));
-       }
+       BOOST_REQUIRE(!logic.haveKey(""));
+       BOOST_REQUIRE_NO_THROW(logic.removeKey(""));
+}
+
+NEGATIVE_TEST_CASE(double_remove_key)
+{
+       CryptoLogic logic;
+
+       BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
+       BOOST_REQUIRE(logic.haveKey(TEST_CLIENT));
+       BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
+       BOOST_REQUIRE(!logic.haveKey(TEST_CLIENT));
+       BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
+       BOOST_REQUIRE(!logic.haveKey(TEST_CLIENT));
 }
 
 NEGATIVE_TEST_CASE(push_key)
 {
        CryptoLogic logic;
 
-       const ClientId client = "test_client";
-       BOOST_REQUIRE_THROW(logic.pushKey(std::string(), createRandom(10)),
-                                               Exc::InternalError);
-       BOOST_REQUIRE_THROW(logic.pushKey(client, RawBuffer()),
-                                               Exc::InternalError);
-
-       BOOST_REQUIRE_NO_THROW(logic.pushKey(client, createRandom(10)));
-       BOOST_REQUIRE_THROW(logic.pushKey(client, createRandom(10)),
-                                               Exc::InternalError);
-
-       ClientId increasingOwner = "a";
-       for (size_t i = 0; i < 20; ++i, increasingOwner.push_back('a')) {
-               BOOST_REQUIRE_NO_THROW(logic.pushKey(increasingOwner, createRandom(10)));
-               BOOST_REQUIRE_THROW(logic.pushKey(increasingOwner, createRandom(10)),
-                                                       Exc::InternalError);
+       BOOST_REQUIRE_THROW(logic.pushKey("", TEST_KEY), Exc::InternalError);
+       BOOST_REQUIRE_THROW(logic.pushKey(TEST_CLIENT, RawBuffer()), Exc::InternalError);
+
+       char client[] = "duck";
+       for (size_t i = 0; i < 20; ++i) {
+               ++client[0];
+               BOOST_REQUIRE(!logic.haveKey(client));
+               BOOST_REQUIRE_NO_THROW(logic.pushKey(client, TEST_KEY));
+               BOOST_REQUIRE_THROW(logic.pushKey(client, TEST_KEY), Exc::InternalError);
+               BOOST_REQUIRE(logic.haveKey(client));
        }
 }
 
 POSITIVE_TEST_CASE(row_encryption)
 {
-       Policy policy(Password(), true);
-       Crypto::Data data(DataType(DataType::Type::BINARY_DATA), createRandom(10));
+       Policy policy("", true);
+       Crypto::Data data(DataType(DataType::Type::BINARY_DATA), TEST_DATA);
        Crypto::Decider decider;
        Crypto::GStore &store = decider.getStore(data.type, policy);
        Token token = store.import(data, policy.password, Crypto::EncryptionParams());
 
-       Name name = "test_data";
-       ClientId owner = "test_owner";
-       DB::Row row(token, name, owner, static_cast<int>(policy.extractable));
+       DB::Row row(token, TEST_NAME, TEST_CLIENT, static_cast<int>(policy.extractable));
 
        CryptoLogic logic;
 
-       auto key = createRandom(32);
-       BOOST_REQUIRE_NO_THROW(logic.pushKey(owner, key));
-       BOOST_REQUIRE_NO_THROW(logic.encryptRow(row));
-       BOOST_REQUIRE_NO_THROW(logic.decryptRow(policy.password, row));
+       DB::Row rowCopy = row;
+       BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
+       BOOST_REQUIRE_NO_THROW(logic.encryptRow(rowCopy));
+       BOOST_REQUIRE(rowCopy.algorithmType == DBCMAlgType::AES_GCM_256);
+       BOOST_REQUIRE(rowCopy.dataSize == static_cast<int>(row.data.size()));
+       BOOST_REQUIRE(!rowCopy.iv.empty());
+       BOOST_REQUIRE(!rowCopy.tag.empty());
+       auto scheme = CryptoLogic::getSchemeVersion(rowCopy.encryptionScheme);
+       BOOST_REQUIRE(scheme == CryptoLogic::ENCRYPTION_V2);
+
+       BOOST_REQUIRE_NO_THROW(logic.decryptRow(policy.password, rowCopy));
+       BOOST_REQUIRE(row.data == rowCopy.data);
 }
 
 NEGATIVE_TEST_CASE(row_encryption)
 {
-       Policy policy(Password(), true);
-       Crypto::Data data(DataType(DataType::Type::BINARY_DATA), createRandom(10));
+       const Policy policy("", true);
+       Crypto::Data data(DataType(DataType::Type::BINARY_DATA), TEST_DATA);
        Crypto::Decider decider;
        Crypto::GStore &store = decider.getStore(data.type, policy);
        Token token = store.import(data, policy.password, Crypto::EncryptionParams());
 
-       Name name = "test_data";
-       ClientId owner = "test_owner";
-       DB::Row row(token, name, owner, static_cast<int>(policy.extractable));
+       DB::Row row(token, TEST_NAME, TEST_CLIENT, static_cast<int>(policy.extractable));
 
        CryptoLogic logic;
 
+       // empty row
+       DB::Row emptyRow;
+       BOOST_REQUIRE_THROW(logic.encryptRow(emptyRow), Exc::InternalError);
+
+       // no key
        BOOST_REQUIRE_THROW(logic.encryptRow(row), Exc::InternalError);
 
-       auto key = createRandom(32);
-       BOOST_REQUIRE_NO_THROW(logic.pushKey(owner, key));
-       BOOST_REQUIRE_NO_THROW(logic.encryptRow(row));
+       // short key
+       const auto shortKey = RawBuffer(4);
+       BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, shortKey));
+       BOOST_REQUIRE_THROW(logic.encryptRow(row), Exc::InternalError);
+       BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
+       BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
 
-       BOOST_REQUIRE_THROW(logic.decryptRow(createRandomPass(10), row),
-                                               Exc::AuthenticationFailed);
+       // short IV
+       row.iv = RawBuffer(4);
+       BOOST_REQUIRE_THROW(logic.encryptRow(row), Exc::InternalError);
+       row.iv.clear();
 
-       BOOST_REQUIRE_NO_THROW(logic.removeKey(owner));
-       BOOST_REQUIRE_THROW(logic.decryptRow(Password(), row),
-                                               Exc::AuthenticationFailed);
-       BOOST_REQUIRE_NO_THROW(logic.pushKey(owner, key));
+       // correct encryption
+       BOOST_REQUIRE_NO_THROW(logic.encryptRow(row));
 
+       // wrong algorithm
        row.algorithmType = DBCMAlgType::NONE;
-       BOOST_REQUIRE_THROW(logic.decryptRow(Password(), row),
+       BOOST_REQUIRE_THROW(logic.decryptRow("", row), Exc::AuthenticationFailed);
+       row.algorithmType = DBCMAlgType::AES_GCM_256;
+
+       // unnecessary password
+       BOOST_REQUIRE_THROW(logic.decryptRow("unnecessary password", row),
                                                Exc::AuthenticationFailed);
+
+       // no key
+       BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
+       BOOST_REQUIRE_THROW(logic.decryptRow("", row), Exc::AuthenticationFailed);
+       BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
+
+       // wrong owner
+       ++row.owner[0];
+       BOOST_REQUIRE_THROW(logic.decryptRow("", row), Exc::AuthenticationFailed);
+       --row.owner[0];
+
+       // no iv
+       auto rowCopy = row;
+       rowCopy.iv.clear();
+       BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError);
+
+       // wrong iv (not base64)
+       rowCopy = row;
+       rowCopy.iv[0] = 64;
+       BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError);
+
+       // wrong iv
+       rowCopy = row;
+       changeBase64(rowCopy.iv);
+       BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed);
+
+       // no ciphertext
+       rowCopy = row;
+       rowCopy.data.clear();
+       BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy),Exc::InternalError);
+
+       // wrong ciphertext (not base64)
+       rowCopy = row;
+       rowCopy.data[0] = 64;
+       BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError);
+
+       // wrong ciphertext
+       rowCopy = row;
+       changeBase64(rowCopy.data);
+       BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed);
+
+       // wrong tag
+       rowCopy = row;
+       ++rowCopy.tag[0];
+       BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed);
+
+       // wrong dataSize
+       rowCopy = row;
+       ++rowCopy.dataSize;
+       BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // CRYPTO_LOGIC_TEST