#include <test_common.h>
#include <iostream>
+#include "crypto-backend.h"
+
using namespace CKM;
namespace {
const std::string USERNAME = "SOFTWARE_CENTER_SYSTEM_SW_LAB";
const std::string CLIENT_ID = "SAMPLE_CLIENT_ID_1";
+constexpr uint32_t KEYCOMPONENT_VERSION = 2; // keep it in sync with key-provider.cpp
+
+template<typename T>
+RawBuffer toRawBuffer(const T &data)
+{
+ RawBuffer output;
+ const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&data);
+ output.assign(ptr, ptr + sizeof(T));
+ return output;
+}
+
RawBuffer makeDefaultWrappedDomainKEK()
{
RawBuffer wdkek;
return kp;
}
+RawBuffer makeDefaultWrappedDomainKEK(CryptoBackend backend)
+{
+ struct TestKeyProvider : public KeyProvider {
+ using KeyProvider::KeyProvider;
+
+ void setBackend(CryptoBackend backend) {
+ BOOST_REQUIRE(m_domainKEK);
+ m_domainKEK->info.backend = static_cast<uint32_t>(backend);
+ }
+ };
+
+ auto wrappedDKEKbuffer = makeDefaultWrappedDomainKEK();
+ TestKeyProvider kp(wrappedDKEKbuffer, PASSWORD);
+ kp.setBackend(backend);
+ return kp.getWrappedDomainKEK(PASSWORD);
+}
+
+void checkVersionAndBackend(const RawBuffer& wrappedDomainKEKbuffer)
+{
+ DomainKEKAndInfo wdkek(wrappedDomainKEKbuffer);
+ BOOST_REQUIRE(wdkek.info.version == KEYCOMPONENT_VERSION);
+#if SE_BACKEND_ENABLED
+ BOOST_REQUIRE(wdkek.info.backend == static_cast<uint32_t>(CryptoBackend::SecureElement));
+#else
+ BOOST_REQUIRE(wdkek.info.backend == static_cast<uint32_t>(CryptoBackend::OpenSSL));
+#endif
+}
+
+RawBuffer convertToOldFormat(const RawBuffer& wrappedDKEKbuffer)
+{
+ DomainKEKAndInfo wrappedDKEK(wrappedDKEKbuffer);
+ DEKAndInfo wrappedOldDKEK;
+
+ // hacky conversion to old key format
+ wrappedOldDKEK.setKeyInfo(static_cast<KeyInfo>(wrappedDKEK.info));
+ memcpy(wrappedOldDKEK.key, wrappedDKEK.key, wrappedDKEK.info.keyLength);
+
+ return toRawBuffer(wrappedOldDKEK);
+}
+
} // anonymous namespace
BOOST_AUTO_TEST_SUITE(KEY_PROVIDER_TEST)
+NEGATIVE_TEST_CASE(KeyAndInfo_ctor_wrong_size)
+{
+ RawBuffer buffer(sizeof(DomainKEKAndInfo) + 1, 0);
+ BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer)), Exc::InternalError);
+ buffer.pop_back();
+ buffer.pop_back();
+ BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer)), Exc::InternalError);
+
+ buffer.resize(sizeof(DEKAndInfo) + 1, 0);
+ BOOST_REQUIRE_THROW((DEKAndInfo(buffer)), Exc::InternalError);
+ buffer.pop_back();
+ buffer.pop_back();
+ BOOST_REQUIRE_THROW((DEKAndInfo(buffer)), Exc::InternalError);
+}
+
+NEGATIVE_TEST_CASE(KeyAndInfo_ctor_wrong_key_length)
+{
+ DomainKEKAndInfo dkek;
+ dkek.info.keyLength = MAX_KEY_SIZE+1;
+ auto buffer = toRawBuffer(dkek);
+
+ BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer)), Exc::InternalError);
+
+ DEKAndInfo dek;
+ dek.info.keyLength = MAX_KEY_SIZE+1;
+ auto buffer2 = toRawBuffer(dek);
+
+ BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer2)), Exc::InternalError);
+}
+
+NEGATIVE_TEST_CASE(KeyAndInfo_ctor_wrong_client)
+{
+ DomainKEKAndInfo dkek;
+ memset(&dkek.info.client, 'a', MAX_CLIENT_ID_SIZE);
+ auto buffer = toRawBuffer(dkek);
+
+ BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer)), Exc::InternalError);
+
+ DEKAndInfo dek;
+ memset(&dek.info.client, 'a', MAX_CLIENT_ID_SIZE);
+ auto buffer2 = toRawBuffer(dek);
+
+ BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer2)), Exc::InternalError);
+}
+
+POSITIVE_TEST_CASE(KeyAndInfo_ctor)
+{
+ BOOST_REQUIRE_NO_THROW(DomainKEKAndInfo(RawBuffer(sizeof(DomainKEKAndInfo), 0)));
+
+ BOOST_REQUIRE_NO_THROW(DEKAndInfo(RawBuffer(sizeof(DEKAndInfo), 0)));
+}
+
NEGATIVE_TEST_CASE(KeyProvider_wrong_size)
{
RawBuffer wdkek = makeDefaultWrappedDomainKEK();
BOOST_REQUIRE_NO_THROW(dkek = kp.getPureDomainKEK());
BOOST_REQUIRE(dkek.size() <= MAX_KEY_SIZE);
+
+ checkVersionAndBackend(kp.getWrappedDomainKEK("whatever"));
}
NEGATIVE_TEST_CASE(KeygetPureDomainKEK_uninitialized)
BOOST_REQUIRE_THROW(kp.getPureDEK(wdek), Exc::InternalError);
}
+POSITIVE_TEST_CASE(WrappedDomainKEK)
+{
+ RawBuffer wdkekBuffer = makeDefaultWrappedDomainKEK();
+
+ checkVersionAndBackend(wdkekBuffer);
+}
+
POSITIVE_TEST_CASE(KeyReencrypt)
{
RawBuffer wdkek = makeDefaultWrappedDomainKEK();
DEKAndInfo dai2;
dai2.info.keyLength = MAX_KEY_SIZE + 1;
-
- const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&dai2);
- RawBuffer buffer(ptr, ptr + sizeof(dai2));
+ auto buffer = toRawBuffer(dai2);
BOOST_REQUIRE_THROW(new DEKAndInfo((buffer)), Exc::InternalError);
// missing NULL termination in dai3.info.client
BOOST_REQUIRE_THROW(kp.getPureDomainKEK(), Exc::InternalError);
}
+NEGATIVE_TEST_CASE(migration)
+{
+ // migration may only happen in case of openssl backend
+ auto wrappedDKEKbuffer = makeDefaultWrappedDomainKEK(CryptoBackend::OpenSSL);
+
+ KeyProvider kp(RawBuffer(), "whatever");
+ BOOST_REQUIRE(!kp.isInitialized());
+
+ // migration possible only from old shorter format
+ BOOST_REQUIRE_THROW(kp.migrateDomainKEK(wrappedDKEKbuffer, PASSWORD), Exc::InternalError);
+ BOOST_REQUIRE(!kp.isInitialized());
+
+ auto wrappedOldDKEKbuffer = convertToOldFormat(wrappedDKEKbuffer);
+
+ KeyProvider kp2(wrappedOldDKEKbuffer, PASSWORD);
+ BOOST_REQUIRE(!kp2.isInitialized());
+ BOOST_REQUIRE_THROW(kp2.migrateDomainKEK(wrappedOldDKEKbuffer, INCORRECT_PASSWORD),
+ Exc::AuthenticationFailed);
+ BOOST_REQUIRE(!kp2.isInitialized());
+}
+
+POSITIVE_TEST_CASE(migration)
+{
+ // migration may only happen in case of openssl backend
+ auto wrappedDKEKbuffer = makeDefaultWrappedDomainKEK(CryptoBackend::OpenSSL);
+ KeyProvider kp(wrappedDKEKbuffer, PASSWORD);
+
+ auto wrappedOldDKEKbuffer = convertToOldFormat(wrappedDKEKbuffer);
+
+ KeyProvider kp2;
+ BOOST_REQUIRE_NO_THROW(kp2 = KeyProvider(wrappedOldDKEKbuffer, PASSWORD));
+ BOOST_REQUIRE(!kp2.isInitialized());
+ BOOST_REQUIRE_NO_THROW(kp2.migrateDomainKEK(wrappedOldDKEKbuffer, PASSWORD));
+ BOOST_REQUIRE(kp2.isInitialized());
+
+ BOOST_REQUIRE(kp.getPureDomainKEK() == kp2.getPureDomainKEK());
+
+ checkVersionAndBackend(kp2.getWrappedDomainKEK("whatever"));
+}
+
+NEGATIVE_TEST_CASE(version)
+{
+ auto wrappedDKEKbuffer = makeDefaultWrappedDomainKEK();
+ DomainKEKAndInfo wrappedDKEK(wrappedDKEKbuffer);
+ wrappedDKEK.info.version = 0;
+
+ auto wrappedWrongVersionBuffer = toRawBuffer(wrappedDKEK);
+ BOOST_REQUIRE_THROW(KeyProvider(wrappedWrongVersionBuffer, PASSWORD), Exc::InternalError);
+}
+
+NEGATIVE_TEST_CASE(backend)
+{
+ auto throwForBackend = [](CryptoBackend backend){
+ BOOST_REQUIRE_THROW(KeyProvider(makeDefaultWrappedDomainKEK(backend), PASSWORD),
+ Exc::InternalError);
+ };
+
+ throwForBackend(CryptoBackend::None);
+ throwForBackend(CryptoBackend::TrustZone);
+ throwForBackend(static_cast<CryptoBackend>(999));
+
+#ifndef SE_BACKEND_ENABLED
+ throwForBackend(CryptoBackend::SecureElement);
+#endif
+}
+
+#ifdef SE_BACKEND_ENABLED
+POSITIVE_TEST_CASE(backend)
+{
+ KeyProvider kp;
+ BOOST_REQUIRE_NO_THROW(
+ kp = KeyProvider(makeDefaultWrappedDomainKEK(CryptoBackend::OpenSSL), PASSWORD));
+ DomainKEKAndInfo wdkek(kp.getWrappedDomainKEK("whatever"));
+ BOOST_REQUIRE(wdkek.info.backend == static_cast<uint32_t>(CryptoBackend::OpenSSL));
+}
+#endif
+
BOOST_AUTO_TEST_SUITE_END()