#include <platform/decider.h>
#include <generic-backend/gstore.h>
#include <db-row.h>
+#include <base64.h>
#include <utility>
#include <cstdlib>
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
{
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