From 071f6d35947803c7c8fc1b57f5af82b2f38e53d1 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Thu, 26 Mar 2020 21:10:05 +0100 Subject: [PATCH] Improve CryptoLogic tests code coverage Change-Id: I14d50f0269166931e7d4b9a7591c8186eff7d16a --- src/manager/service/crypto-logic.cpp | 16 +-- src/manager/service/crypto-logic.h | 6 +- tests/test_crypto-logic.cpp | 218 +++++++++++++++++++++++++---------- 3 files changed, 162 insertions(+), 78 deletions(-) diff --git a/src/manager/service/crypto-logic.cpp b/src/manager/service/crypto-logic.cpp index d15a37c..6de54dc 100644 --- a/src/manager/service/crypto-logic.cpp +++ b/src/manager/service/crypto-logic.cpp @@ -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); diff --git a/src/manager/service/crypto-logic.h b/src/manager/service/crypto-logic.h index 154b1b2..75cad96 100644 --- a/src/manager/service/crypto-logic.h +++ b/src/manager/service/crypto-logic.h @@ -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() {} diff --git a/tests/test_crypto-logic.cpp b/tests/test_crypto-logic.cpp index 142489a..84bed8b 100644 --- a/tests/test_crypto-logic.cpp +++ b/tests/test_crypto-logic.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -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(::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(policy.extractable)); + DB::Row row(token, TEST_NAME, TEST_CLIENT, static_cast(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(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(policy.extractable)); + DB::Row row(token, TEST_NAME, TEST_CLIENT, static_cast(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 -- 2.7.4