From: Krzysztof Jackiewicz Date: Thu, 24 Sep 2015 09:21:03 +0000 (+0200) Subject: Add encryption scheme tests X-Git-Tag: accepted/tizen/mobile/20151230.112505~25 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F67%2F48667%2F21;p=platform%2Fcore%2Fsecurity%2Fkey-manager.git Add encryption scheme tests [Problem] We need tests that will verify correctness of old and new encryption scheme support. [Solution] Tests added. [Verification] Run ckm-tests-internal -t ENCRYPTION_SCHEME_TEST Change-Id: I9f4e24a9e06684d401540646d5560287e35b828d --- diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 62fea85..8cadd63 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -29,6 +29,7 @@ INCLUDE_DIRECTORIES( ${KEY_MANAGER_PATH}/client-async/ ${KEY_MANAGER_SRC_PATH}/include ${KEY_MANAGER_TEST_MERGED_SRC}/ + ${KEY_MANAGER_TEST_MERGED_SRC}/encryption-scheme/ ) SET(TEST_MERGED_SOURCES @@ -44,6 +45,7 @@ SET(TEST_MERGED_SOURCES ${KEY_MANAGER_TEST_MERGED_SRC}/test_comm-manager.cpp ${KEY_MANAGER_TEST_MERGED_SRC}/test_serialization.cpp ${KEY_MANAGER_TEST_MERGED_SRC}/test_xml-parser.cpp + ${KEY_MANAGER_TEST_MERGED_SRC}/test_encryption-scheme.cpp ${KEY_MANAGER_PATH}/service/db-crypto.cpp ${KEY_MANAGER_PATH}/service/key-provider.cpp ${KEY_MANAGER_PATH}/initial-values/parser.cpp @@ -62,6 +64,7 @@ TARGET_LINK_LIBRARIES(${TARGET_TEST_MERGED} ${TARGET_KEY_MANAGER_COMMON} ${CMAKE_THREAD_LIBS_INIT} ${KEY_MANAGER_DEP_LIBRARIES} + ${TARGET_ENCRYPTION_SCHEME_COMMON} boost_unit_test_framework -ldl ) diff --git a/tests/encryption-scheme/CMakeLists.txt b/tests/encryption-scheme/CMakeLists.txt index 8503859..10cea93 100644 --- a/tests/encryption-scheme/CMakeLists.txt +++ b/tests/encryption-scheme/CMakeLists.txt @@ -21,16 +21,39 @@ INCLUDE(FindPkgConfig) # common encryption scheme library PKG_CHECK_MODULES(ENCRYPTION_SCHEME_DEP - libsmack - REQUIRED) + REQUIRED + openssl + libcrypto + libsmack) + +FIND_PACKAGE(Threads REQUIRED) SET(ENCRYPTION_SCHEME_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/smack-access.cpp ${CMAKE_CURRENT_SOURCE_DIR}/scheme-test.cpp + + ${KEY_MANAGER_PATH}/service/file-lock.cpp + ${KEY_MANAGER_PATH}/service/key-provider.cpp + ${KEY_MANAGER_PATH}/service/db-crypto.cpp + ${KEY_MANAGER_PATH}/service/file-system.cpp + ${KEY_MANAGER_PATH}/dpl/core/src/assert.cpp + ${KEY_MANAGER_PATH}/dpl/db/src/sql_connection.cpp + ${KEY_MANAGER_PATH}/dpl/db/src/naive_synchronization_object.cpp + ${KEY_MANAGER_PATH}/sqlcipher/sqlcipher.c ) INCLUDE_DIRECTORIES(SYSTEM ${ENCRYPTION_SCHEME_DEP_INCLUDE_DIRS}) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR} + + ${KEY_MANAGER_PATH}/common + ${KEY_MANAGER_PATH}/dpl/core/include + ${KEY_MANAGER_PATH}/dpl/log/include + ${KEY_MANAGER_PATH}/dpl/db/include + ${KEY_MANAGER_PATH}/sqlcipher + ${KEY_MANAGER_PATH}/service + ${KEY_MANAGER_PATH}/crypto +) ADD_LIBRARY(${TARGET_ENCRYPTION_SCHEME_COMMON} STATIC ${ENCRYPTION_SCHEME_SOURCES}) @@ -38,6 +61,9 @@ TARGET_LINK_LIBRARIES(${TARGET_ENCRYPTION_SCHEME_COMMON} ${ENCRYPTION_SCHEME_DEP_LIBRARIES} ${TARGET_KEY_MANAGER_CLIENT} ${TARGET_KEY_MANAGER_CONTROL_CLIENT} + ${CMAKE_THREAD_LIBS_INIT} + boost_unit_test_framework + -ldl ) INSTALL(TARGETS ${TARGET_ENCRYPTION_SCHEME_COMMON} DESTINATION ${LIB_INSTALL_DIR}) diff --git a/tests/encryption-scheme/scheme-test.cpp b/tests/encryption-scheme/scheme-test.cpp index 5422bd2..102bb69 100644 --- a/tests/encryption-scheme/scheme-test.cpp +++ b/tests/encryption-scheme/scheme-test.cpp @@ -22,13 +22,25 @@ #include #include +#include +#include +#include #include +#include #include #include +#include + #include +#include +#include +#include +#include +#include + using namespace CKM; using namespace std; @@ -37,9 +49,13 @@ const uid_t UID = 7654; const gid_t GID = 7654; const char* const DBPASS = "db-pass"; const char* const LABEL = "my-label"; +const Label DB_LABEL = "/" + string(LABEL); +const int ENC_SCHEME_OFFSET = 24; const string TEST_DATA_STR = "test-data"; RawBuffer TEST_DATA(TEST_DATA_STR.begin(), TEST_DATA_STR.end()); const Password TEST_PASS = "custom user password"; +const size_t IV_LEN = 16; +const size_t CHAIN_LEN = 3; enum { NO_PASS = 0, @@ -59,9 +75,9 @@ Policy policy[2][2] = { struct Group { enum { - KEY_PAIR, - CERT_CHAIN, - SINGLE_ITEM + SINGLE_ITEM, + KEY_PAIR_RSA, + CERT_CHAIN } type; Items items; }; @@ -76,24 +92,24 @@ Group GROUPS[] = { }}, // RSA keys - { Group::KEY_PAIR, { + { Group::KEY_PAIR_RSA, { Item("key-rsa-alias-prv1", DataType::KEY_RSA_PRIVATE, policy[NO_PASS][NO_EXP]), Item("key-rsa-alias-pub1", DataType::KEY_RSA_PUBLIC, policy[NO_PASS][NO_EXP]) }}, - { Group::KEY_PAIR, { + { Group::KEY_PAIR_RSA, { Item("key-rsa-alias-prv2", DataType::KEY_RSA_PRIVATE, policy[NO_PASS][EXP]), Item("key-rsa-alias-pub2", DataType::KEY_RSA_PUBLIC, policy[NO_PASS][EXP]), }}, - { Group::KEY_PAIR, { + { Group::KEY_PAIR_RSA, { Item("key-rsa-alias-prv3", DataType::KEY_RSA_PRIVATE, policy[PASS][NO_EXP]), Item("key-rsa-alias-pub3", DataType::KEY_RSA_PUBLIC, policy[PASS][NO_EXP]), }}, - { Group::KEY_PAIR, { + { Group::KEY_PAIR_RSA, { Item("key-rsa-alias-prv4", DataType::KEY_RSA_PRIVATE, policy[PASS][EXP]), Item("key-rsa-alias-pub4", DataType::KEY_RSA_PUBLIC, policy[PASS][EXP]), }}, // different policies - { Group::KEY_PAIR, { + { Group::KEY_PAIR_RSA, { Item("key-rsa-alias-prv5", DataType::KEY_RSA_PRIVATE, policy[PASS][NO_EXP]), Item("key-rsa-alias-pub5", DataType::KEY_RSA_PUBLIC, policy[NO_PASS][EXP]), }}, @@ -223,12 +239,71 @@ std::string TEST_LEAF = "Zj/T1JkYXKkEwZU6nAR2jdZp3EP9xj3o15V/tyFcXHx6l8NTxn4cJb+Xe4VquQJz\n" "6ON7PVe0ABN/AlwVQiFE\n" "-----END CERTIFICATE-----\n"; + + + +struct FdCloser { + void operator()(int* fd) { + if(fd) + close(*fd); + } +}; + +typedef std::unique_ptr FdPtr; + +void restoreFile(const string& filename) { + string sourcePath = "/usr/share/ckm-db-test/" + filename; + string targetPath = "/opt/data/ckm/" + filename; + + int ret; + + int sourceFd = TEMP_FAILURE_RETRY(open(sourcePath.c_str(), O_RDONLY)); + BOOST_REQUIRE_MESSAGE(sourceFd > 0, "Opening " << sourcePath << " failed."); + + FdPtr sourceFdPtr(&sourceFd); + + int targetFd = TEMP_FAILURE_RETRY(creat(targetPath.c_str(), 666)); + BOOST_REQUIRE_MESSAGE(targetFd > 0, "Creating " << targetPath << " failed."); + + FdPtr targetFdPtr(&targetFd); + + struct stat sourceStat; + ret = fstat(sourceFd, &sourceStat); + BOOST_REQUIRE_MESSAGE(ret != -1, "fstat() failed: " << ret); + + ret = sendfile(targetFd, sourceFd, 0, sourceStat.st_size); + BOOST_REQUIRE_MESSAGE(ret != -1, "sendfile failed: " << ret); + + ret = fsync(targetFd); + BOOST_REQUIRE_MESSAGE(ret != -1, "fsync failed: " << ret); +} + +void generateRandom(size_t random_bytes, unsigned char *output) +{ + if(random_bytes<=0 || !output) + throw runtime_error("Invalid param"); + + std::ifstream is("/dev/urandom", std::ifstream::binary); + if(!is) + throw runtime_error("Failed to read /dev/urandom"); + is.read(reinterpret_cast(output), random_bytes); + if(static_cast(random_bytes) != is.gcount()) + throw runtime_error("Not enough bytes read from /dev/urandom"); +} + +RawBuffer createRandomBuffer(size_t random_bytes) +{ + RawBuffer buffer(random_bytes); + generateRandom(buffer.size(), buffer.data()); + return buffer; +} } // namespace anonymous -SchemeTest::SchemeTest() : m_userChanged(false) { +SchemeTest::SchemeTest() : m_userChanged(false), m_directAccessEnabled(false) { m_control = Control::create(); m_mgr = Manager::create(); + initOpenSsl(); SmackAccess sa; sa.add("System", LABEL, "rwx"); @@ -243,6 +318,14 @@ SchemeTest::~SchemeTest() { } catch (...) {} } +void SchemeTest::RemoveUserData() { + if(CKM_API_SUCCESS != m_control->lockUserKey(UID)) + throw runtime_error("lockUserKey failed"); + + if(CKM_API_SUCCESS != m_control->removeUserData(UID)) + throw runtime_error("removeUserData failed"); +} + void SchemeTest::SwitchToUser() { if (m_userChanged) return; @@ -309,7 +392,7 @@ void SchemeTest::FillDb() { for(const auto& g:GROUPS) { switch (g.type) { - case Group::KEY_PAIR: + case Group::KEY_PAIR_RSA: if(g.items.size() != 2) throw runtime_error("Wrong number of keys"); if( g.items[0].type != DataType::KEY_RSA_PRIVATE || @@ -366,3 +449,306 @@ void SchemeTest::FillDb() { } } } + +void SchemeTest::ReadAll(bool useWrongPass) { + SwitchToUser(); + + for(const auto& g:GROUPS) { + for(const auto& i:g.items) { + int ret; + Password pass = i.policy.password; + if(useWrongPass) { + if(pass.empty()) + pass = TEST_PASS; + else + pass = Password(); + } + + switch (i.type) { + case DataType::BINARY_DATA: + { + RawBuffer receivedData; + ret = m_mgr->getData(i.alias, pass, receivedData); + BOOST_REQUIRE_MESSAGE(useWrongPass || receivedData == TEST_DATA, + "Received data is different for " << i.alias); + break; + } + + case DataType::KEY_AES: + case DataType::KEY_RSA_PRIVATE: + case DataType::KEY_RSA_PUBLIC: + { + KeyShPtr receivedKey; + ret = m_mgr->getKey(i.alias, pass, receivedKey); + break; + } + + case DataType::CERTIFICATE: + { + CertificateShPtr receivedCert; + ret = m_mgr->getCertificate(i.alias, pass, receivedCert); + break; + } + + case DataType::CHAIN_CERT_0: // pkcs + { + PKCS12ShPtr pkcs; + ret = m_mgr->getPKCS12(i.alias, pass, pass, pkcs); + break; + } + + default: + BOOST_FAIL("Unsupported data type " << i.type); + } + + if(i.policy.extractable) { + if(useWrongPass) + BOOST_REQUIRE_MESSAGE(ret == CKM_API_ERROR_AUTHENTICATION_FAILED, + "Reading item " << i.alias << " should fail with " << + CKM_API_ERROR_AUTHENTICATION_FAILED << " got: " << ret); + else + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "Reading item " << i.alias << + " failed with " << ret); + } + else + BOOST_REQUIRE_MESSAGE(ret == CKM_API_ERROR_NOT_EXPORTABLE, "Item " << i.alias << + " should not be exportable"); + } + } +} + +void SchemeTest::SignVerify() { + SwitchToUser(); + + for(const auto& g:GROUPS) { + if(g.type == Group::KEY_PAIR_RSA) { + BOOST_REQUIRE_MESSAGE(g.items.size() == 2, "Wrong number of keys"); + BOOST_REQUIRE_MESSAGE(g.items[0].type == DataType::KEY_RSA_PRIVATE && + g.items[1].type == DataType::KEY_RSA_PUBLIC, "Wrong key"); + + SignVerifyItem(g.items[0], g.items[1]); + } else { + for(const auto& i:g.items) { + switch (i.type) { + case DataType::CHAIN_CERT_0: + SignVerifyItem(i, i); + break; + + default: + break; + } + } + } + } +} + +void SchemeTest::EncryptDecrypt() { + SwitchToUser(); + + for(const auto& g:GROUPS) { + if(g.type == Group::KEY_PAIR_RSA) { + BOOST_REQUIRE_MESSAGE(g.items.size() == 2, "Wrong number of keys"); + BOOST_REQUIRE_MESSAGE(g.items[0].type == DataType::KEY_RSA_PRIVATE && + g.items[1].type == DataType::KEY_RSA_PUBLIC, "Wrong key"); + + EncryptDecryptItem(g.items[0], g.items[1]); + } else { + for(const auto& i:g.items) { + switch (i.type) { + case DataType::KEY_AES: + EncryptDecryptItem(i); + break; + + case DataType::CHAIN_CERT_0: + EncryptDecryptItem(i, i); + break; + + default: + break; + } + } + } + } +} + +void SchemeTest::CreateChain() { + SwitchToUser(); + + for(const auto& g:GROUPS) { + if(g.type == Group::CERT_CHAIN) { + BOOST_REQUIRE_MESSAGE(g.items.size() == CHAIN_SIZE, "Not enough certificates"); + for(const auto& c:g.items) + BOOST_REQUIRE_MESSAGE(c.type == DataType::CERTIFICATE, "Wrong item type"); + Items trusted(CHAIN_SIZE-1); + std::copy(g.items.begin(), g.items.begin() + CHAIN_SIZE-1, trusted.begin()); + + // last one is ee (leaf) + CreateChainItem(g.items.back(), trusted); + } else { + for(const auto& i:g.items) { + if(i.type == DataType::CHAIN_CERT_0) // PKCS + CreateChainItem(i, { i }); + } + } + } +} + +void SchemeTest::RemoveAll() { + SwitchToUser(); + + for(const auto& g:GROUPS) { + for(const auto& i:g.items) { + int ret = m_mgr->removeAlias(i.alias); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, + "removeAlias() failed with " << ret << " for " << i.alias); + } + } +} +size_t SchemeTest::CountObjects() { + EnableDirectDbAccess(); + + size_t ret = 0; + for(const auto& g:GROUPS) { + for(const auto& i:g.items) { + DB::RowVector rows; + // it is assumed that aliases are different + m_db->getRows(i.alias, DB_LABEL, DataType::DB_FIRST, DataType::DB_LAST, rows); + ret += rows.size(); + } + } + return ret; +} + +void SchemeTest::RestoreDb() { + restoreFile("key-7654"); + restoreFile("db-key-7654"); + restoreFile("db-7654"); + m_db.reset(); + m_directAccessEnabled = false; +} + +void SchemeTest::CheckSchemeVersion(const ItemFilter& filter, int version) { + EnableDirectDbAccess(); + + for(const auto& g:GROUPS) { + for(const auto& i:g.items) { + if(!filter.Matches(i)) + continue; + + DB::RowVector rows; + m_db->getRows(i.alias, DB_LABEL, filter.typeFrom, filter.typeTo, rows); + BOOST_REQUIRE_MESSAGE(rows.size() > 0, "No rows found for " << i.alias); + for(const auto& r : rows) { + BOOST_REQUIRE_MESSAGE( + (r.encryptionScheme >> ENC_SCHEME_OFFSET) == version, + "Wrong encryption scheme for " << i.alias << ". Expected " << version << + " got: " << (r.encryptionScheme >> ENC_SCHEME_OFFSET)); + } + } + } +} + +void SchemeTest::EnableDirectDbAccess() { + SwitchToRoot(); + + if(m_directAccessEnabled) + return; + + // direct access to db + FileSystem fs(UID); + auto wrappedDKEK = fs.getDKEK(); + auto keyProvider = KeyProvider(wrappedDKEK, DBPASS); + + auto wrappedDatabaseDEK = fs.getDBDEK(); + RawBuffer key = keyProvider.getPureDEK(wrappedDatabaseDEK); + + m_db.reset(new DB::Crypto(fs.getDBPath(), key)); + m_directAccessEnabled = true; +} + +void SchemeTest::SignVerifyItem(const Item& itemPrv, const Item& itemPub) { + int ret; + KeyShPtr receivedKey; + RawBuffer signature; + // create/verify signature + ret = m_mgr->createSignature(itemPrv.alias, + itemPrv.policy.password, + TEST_DATA, + HashAlgorithm::SHA512, + RSAPaddingAlgorithm::X931, + signature); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "createSignature() failed with " << ret << + " for " << itemPrv.alias); + ret = m_mgr->verifySignature(itemPub.alias, + itemPub.policy.password, + TEST_DATA, + signature, + HashAlgorithm::SHA512, + RSAPaddingAlgorithm::X931); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "verifySignature() failed with " << ret << + " for " << itemPub.alias); + +} + +void SchemeTest::EncryptDecryptItem(const Item& item) { + CryptoAlgorithm algo; + RawBuffer iv = createRandomBuffer(IV_LEN); + RawBuffer encrypted, decrypted; + int ret; + + algo.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM); + algo.setParam(ParamName::ED_IV, iv); + + ret = m_mgr->encrypt(algo, item.alias, item.policy.password, TEST_DATA, encrypted); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "encrypt() failed iwth " << ret << " for " << + item.alias); + + ret = m_mgr->decrypt(algo, item.alias, item.policy.password, encrypted, decrypted); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "decrypt() failed iwth " << ret << " for " << + item.alias); + + BOOST_REQUIRE_MESSAGE(decrypted == TEST_DATA, "Decrypted data not equal to original"); +} + +void SchemeTest::EncryptDecryptItem(const Item& itemPrv, const Item& itemPub) { + CryptoAlgorithm algo; + RawBuffer encrypted, decrypted; + int ret; + + algo.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP); + + ret = m_mgr->encrypt(algo, itemPub.alias, itemPub.policy.password, TEST_DATA, encrypted); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "encrypt() failed iwth " << ret << " for " << + itemPub.alias); + + ret = m_mgr->decrypt(algo, itemPrv.alias, itemPrv.policy.password, encrypted, decrypted); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "decrypt() failed iwth " << ret << " for " << + itemPrv.alias); + + BOOST_REQUIRE_MESSAGE(decrypted == TEST_DATA, "Decrypted data not equal to original"); +} + +void SchemeTest::CreateChainItem(const Item& leaf, const Items& certs) { + CertificateShPtrVector chain; + AliasVector trusted; + + if(!leaf.policy.extractable || !leaf.policy.password.empty()) + return; + + for(const auto& i : certs) { + if(!i.policy.extractable || !i.policy.password.empty()) + return; + trusted.push_back(i.alias); + } + + CertificateShPtr leafCrt; + int ret = m_mgr->getCertificate(leaf.alias, leaf.policy.password, leafCrt); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, + "getCertificate failed with " << ret << " for " << + leaf.alias); + + ret = m_mgr->getCertificateChain(leafCrt, AliasVector(), trusted, false, chain); + BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, + "getCertificateChain() failed with " << ret); + BOOST_REQUIRE_MESSAGE(chain.size() == CHAIN_LEN, "Wrong chain length: " << chain.size()); +} diff --git a/tests/encryption-scheme/scheme-test.h b/tests/encryption-scheme/scheme-test.h index 69edd24..6d020b7 100644 --- a/tests/encryption-scheme/scheme-test.h +++ b/tests/encryption-scheme/scheme-test.h @@ -21,15 +21,23 @@ #pragma once +#include #include +#include #include #include #include +namespace CKM { +namespace DB { +class Crypto; +} // DB +} // CKM + struct Item { - Item() : type(CKM::DataType::DB_FIRST){} + Item() {} Item(const CKM::Alias& alias, const CKM::DataType::Type type, const CKM::Policy& policy) @@ -44,19 +52,74 @@ struct Item { typedef std::vector Items; +struct ItemFilter { + ItemFilter() : + typeFrom(CKM::DataType::DB_FIRST), + typeTo(CKM::DataType::DB_LAST), + exportableOnly(false), + noPassword(false) + {} + + explicit ItemFilter(CKM::DataType::Type type) : + typeFrom(type), + typeTo(type), + exportableOnly(false), + noPassword(false) + {} + + ItemFilter(CKM::DataType::Type typeFrom, CKM::DataType::Type typeTo) : + typeFrom(typeFrom), + typeTo(typeTo), + exportableOnly(false), + noPassword(false) + {} + + bool Matches(const Item& item) const { + if(item.type < typeFrom || item.type > typeTo) + return false; + if(exportableOnly && !item.policy.extractable) + return false; + if(noPassword && !item.policy.password.empty()) + return false; + return true; + } + + CKM::DataType::Type typeFrom; + CKM::DataType::Type typeTo; + bool exportableOnly; + bool noPassword; +}; + class SchemeTest { public: SchemeTest(); ~SchemeTest(); + void RemoveUserData(); void FillDb(); + void ReadAll(bool useWrongPass = false); + void SignVerify(); + void EncryptDecrypt(); + void CreateChain(); + void RemoveAll(); + size_t CountObjects(); + void RestoreDb(); + void CheckSchemeVersion(const ItemFilter& filter, int version); private: void SwitchToUser(); void SwitchToRoot(); + void EnableDirectDbAccess(); + void SignVerifyItem(const Item& itemPrv, const Item& itemPub); + void EncryptDecryptItem(const Item& item); + void EncryptDecryptItem(const Item& itemPrv, const Item& itemPub); + void CreateChainItem(const Item& leaf, const Items& certs); CKM::ControlShPtr m_control; CKM::ManagerShPtr m_mgr; std::string m_origLabel; bool m_userChanged; + + std::unique_ptr m_db; + bool m_directAccessEnabled; }; diff --git a/tests/test_encryption-scheme.cpp b/tests/test_encryption-scheme.cpp new file mode 100644 index 0000000..9e4579a --- /dev/null +++ b/tests/test_encryption-scheme.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +/* + * @file test_encryption-scheme.cpp + * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com) + * @version 1.0 + */ + +#include +#include + +#include + +using namespace CKM; + +namespace { +// this is done to limit the amount of code included in binary +const int OLD_ENC_SCHEME = 0; +const int NEW_ENC_SCHEME = 1; +} // namespace anonymous + + +BOOST_AUTO_TEST_SUITE(ENCRYPTION_SCHEME_TEST) + +// Test database should have the old scheme +BOOST_AUTO_TEST_CASE(T010_Check_old_scheme) { + SchemeTest test; + test.RestoreDb(); + + ItemFilter filter; + test.CheckSchemeVersion(filter, OLD_ENC_SCHEME); +} + +// Newly written data should use the new scheme +BOOST_AUTO_TEST_CASE(T020_Check_new_scheme) { + SchemeTest test; + test.RemoveUserData(); + test.FillDb(); + + ItemFilter filter; + test.CheckSchemeVersion(filter, NEW_ENC_SCHEME); +} + +BOOST_AUTO_TEST_CASE(T030_Remove_old_scheme) { + SchemeTest test; + test.RestoreDb(); + test.RemoveAll(); + + size_t aliases = test.CountObjects(); + BOOST_REQUIRE_MESSAGE(aliases == 0, "All aliases should be removed"); +} + +BOOST_AUTO_TEST_CASE(T040_Remove_new_scheme) { + SchemeTest test; + test.RemoveUserData(); + test.FillDb(); + test.RemoveAll(); + + size_t aliases = test.CountObjects(); + BOOST_REQUIRE_MESSAGE(aliases == 0, "All aliases should be removed"); +} + +// Reading old db should reencrypt objects with new scheme +BOOST_AUTO_TEST_CASE(T100_Read) { + SchemeTest test; + test.RestoreDb(); + test.ReadAll(); + + ItemFilter filter; + filter.exportableOnly = true; + test.CheckSchemeVersion(filter, NEW_ENC_SCHEME); +} + +BOOST_AUTO_TEST_CASE(T110_Count_objects_after_read) { + SchemeTest test; + test.RestoreDb(); + size_t orig = test.CountObjects(); + BOOST_REQUIRE_MESSAGE(orig > 0, "No objects in db"); + + test.ReadAll(); + + size_t current = test.CountObjects(); + BOOST_REQUIRE_MESSAGE(current == orig, + "Original number of objects: " << orig << " Current: " << current); +} + +// Reading old db with incorrect passwords should leave the scheme unchanged +BOOST_AUTO_TEST_CASE(T120_Read_wrong_pass) { + SchemeTest test; + test.RestoreDb(); + test.ReadAll(true); + + ItemFilter filter; + test.CheckSchemeVersion(filter, OLD_ENC_SCHEME); +} + +// Signing/verification should reencrypt objects with new scheme +BOOST_AUTO_TEST_CASE(T200_SignVerify) { + SchemeTest test; + test.RestoreDb(); + test.SignVerify(); + + ItemFilter filter(DataType::KEY_RSA_PUBLIC, DataType::KEY_RSA_PRIVATE); + test.CheckSchemeVersion(filter, NEW_ENC_SCHEME); +} + +// Encryption/decryption should reencrypt objects with new scheme +BOOST_AUTO_TEST_CASE(T210_EncryptDecrypt) { + SchemeTest test; + test.RestoreDb(); + test.EncryptDecrypt(); + + ItemFilter filter1(DataType::KEY_RSA_PUBLIC, DataType::KEY_RSA_PRIVATE); + test.CheckSchemeVersion(filter1, NEW_ENC_SCHEME); + + ItemFilter filter2(DataType::KEY_AES); + test.CheckSchemeVersion(filter2, NEW_ENC_SCHEME); +} + +// Chain creation should reencrypt objects with new scheme +BOOST_AUTO_TEST_CASE(T220_CreateChain) { + SchemeTest test; + test.RestoreDb(); + test.CreateChain(); + + // non exportable certificates and certificates protected with passwords can't be used for chain + // creation + ItemFilter filter1(DataType::CERTIFICATE); + filter1.exportableOnly = true; + filter1.noPassword = true; + test.CheckSchemeVersion(filter1, NEW_ENC_SCHEME); + + ItemFilter filter2(DataType::CHAIN_CERT_0, DataType::CHAIN_CERT_15); + filter2.exportableOnly = true; + filter2.noPassword = true; + test.CheckSchemeVersion(filter2, NEW_ENC_SCHEME); +} + +BOOST_AUTO_TEST_SUITE_END()