Add more 32 to 64bit migration issue tests
authorJan Wojtkowski <j.wojtkowski@samsung.com>
Tue, 1 Oct 2024 13:52:33 +0000 (15:52 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 16 Oct 2024 11:55:23 +0000 (13:55 +0200)
Change-Id: Ide0ed57a1c6aa905487b03063eff29c8719be863

src/manager/crypto/sw-backend/store.cpp
src/manager/crypto/sw-backend/store.h
unit-tests/test_serialization.cpp

index f26bf4534b88c8dca3a68121b89381be62b0689b..d283db096c8d454fe62ca9b660fb1c668f2bdcfe 100644 (file)
@@ -141,26 +141,33 @@ Token Store::import(const Data &data, const Password &pass, const EncryptionPara
        return Token(m_backendId, data.type, pack(data.data, pass));
 }
 
+std::pair<RawBuffer, RawBuffer> Store::packPassword(int &scheme,
+                                                                                                       RawBuffer &data,
+                                                                                                       const Password &pass,
+                                                                                                       RawBuffer &iv)
+{
+       iv = generateRandIV();
+       RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH);
+       std::pair<RawBuffer, RawBuffer> ret;
+
+       try {
+               ret = Crypto::SW::Internals::encryptDataAesGcm(key, data, iv,
+                               Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
+       } catch (const Exc::Exception &e) {
+               ThrowErr(Exc::InternalError, "Encryption with custom password failed, internal error");
+       }
+
+       scheme |= EncryptionScheme::PASSWORD;
+       return ret;
+}
+
 RawBuffer Store::pack(const RawBuffer &data, const Password &pass)
 {
        int scheme = EncryptionScheme::NONE;
        RawBuffer packed = data;
-
        if (!pass.empty()) {
-               RawBuffer iv = generateRandIV();
-               RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH);
-
-               std::pair<RawBuffer, RawBuffer> ret;
-
-               try {
-                       ret = Crypto::SW::Internals::encryptDataAesGcm(key, data, iv,
-                                       Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
-               } catch (const Exc::Exception &e) {
-                       ThrowErr(Exc::InternalError, "Encryption with custom password failed, internal error");
-               }
-
-               scheme |= EncryptionScheme::PASSWORD;
-
+               RawBuffer iv;
+               std::pair<RawBuffer, RawBuffer> ret = packPassword(scheme, packed, pass, iv);
                // serialization exceptions will be catched as CKM::Exception and will cause
                // CKM_API_ERROR_SERVER_ERROR
                packed = SerializeMessage(ret.first, iv, ret.second);
index fa61e9bfd0cce25f304891cbdfa2e6b0469171b0..5f9c3e1f646ff87ce17ed3f98c3eba0294ba8d68 100644 (file)
@@ -44,6 +44,10 @@ public:
                                 const RawBuffer &) override;
        void destroy(const Token &) override {}
 
+       static std::pair<RawBuffer, RawBuffer> packPassword(int &scheme,
+                                                                                                               RawBuffer &data,
+                                                                                                               const Password &pass,
+                                                                                                               RawBuffer &iv);
        static RawBuffer pack(const RawBuffer &data, const Password &pass);
        static RawBuffer unpack(const RawBuffer &packed, const Password &pass);
 };
index 9b201cced97a8311cd432349b5f8f5f300c3bb38..2272f7462777834c46d5b65d2dc406dadef15ea9 100644 (file)
@@ -21,6 +21,9 @@
 
 #include <string>
 
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+
 #include <boost_macros_wrapper.h>
 #include <test_common.h>
 
 #include <protocols.h>
 #include <message-buffer.h>
 #include <sw-backend/store.h>
+#include <sw-backend/internals.h>
+#ifdef TZ_BACKEND_ENABLED
+#include <tz-backend/store.h>
+#include <tz-backend/internals.h>
+#endif
+
+#include <generic-backend/crypto-params.h>
+#include <crypto-logic.h>
+
+#include <dpl/log/log.h>
 
 using namespace CKM;
 
@@ -86,21 +99,39 @@ void setParam(CryptoAlgorithm &algo, ParamName name, const T &value,
                                                  " should " << (success ? "succeed" : "fail"));
 }
 
-// This function mimics the serialization on a 64-bit system prior to the fix
-RawBuffer pack64(const RawBuffer& data)
-{
-       struct Writer64 : public IStream {
-               explicit Writer64(uint64_t size) {
-                       m_buffer.reserve(sizeof(size) + size);
-                       Serialization::Serialize(*this, size);
+// This class is used to mimic the serialization on a 64-bit system prior to the fix
+class MessageSerializer64 {
+       struct Sizer64 : IStream {
+               void Read(size_t, void*)
+               {
+                       ThrowErr(Exc::InternalError, "unexpected IStream::Read call in SerializeMessage64");
+               }
+               void Write(size_t num, const void*)
+               {
+                       m_bytes += num;
                }
 
-               void Read(size_t, void*) override {
-                       BOOST_FAIL("Unexpected Read call in Writer.");
+               size_t m_bytes = 0;
+       };
+
+       struct Writer64 : IStream {
+               Writer64(size_t size)
+               {
+                       if (size > std::numeric_limits<uint64_t>::max())
+                               ThrowErr(Exc::InternalError, "Message too large for serialization");
+
+                       uint64_t size64 = size;
+                       m_buffer.reserve(sizeof(size64) + size64);
+                       Serialization::Serialize(*this, size64);
                }
 
-               void Write(size_t num, const void* bytes) override {
-                       BOOST_REQUIRE(m_buffer.size() + num <= m_buffer.capacity());
+               void Read(size_t, void*)
+               {
+                       ThrowErr(Exc::InternalError, "unexpected IStream::Read call in SerializeMessage64");
+               }
+               void Write(size_t num, const void* bytes)
+               {
+                       assert(m_buffer.size() + num <= m_buffer.capacity());
                        m_buffer.resize(m_buffer.size() + num);
                        memcpy(&m_buffer[m_buffer.size() - num], bytes, num);
                }
@@ -108,16 +139,56 @@ RawBuffer pack64(const RawBuffer& data)
                RawBuffer m_buffer;
        };
 
+       MessageSerializer64() = delete;
+
+public:
+       template <typename... T>
+       static RawBuffer Run64(const T&... args)
+       {
+               Sizer64 sizer;
+               Serializer<T...>::Serialize(sizer, args...);
+               Writer64 writer(sizer.m_bytes);
+               Serializer<T...>::Serialize(writer, args...);
+               return std::move(writer.m_buffer);
+       }
+};
+
+template <typename... T>
+RawBuffer SerializeMessage64(const T&... args)
+{
+       return MessageSerializer64::Run64(args...);
+}
+
+RawBuffer pack64SW(const RawBuffer& data, const Password &pass)
+{
        int scheme = 0;
-       int dataSize = data.size();
-       uint64_t size64 = sizeof(scheme) + sizeof(dataSize) + data.size();
-       Writer64 writer(sizeof(size64) + size64);
-       Serialization::Serialize(writer, scheme);
-       Serialization::Serialize(writer, data);
-       BOOST_REQUIRE(writer.m_buffer.size() == sizeof(size64) + size64);
-
-       return writer.m_buffer;
+       RawBuffer packed = data;
+       if (!pass.empty()) {
+               RawBuffer iv;
+               std::pair<RawBuffer, RawBuffer> ret = Crypto::SW::Store::packPassword(scheme, packed, pass, iv);
+               // serialization exceptions will be catched as CKM::Exception and will cause
+               // CKM_API_ERROR_SERVER_ERROR
+               packed = SerializeMessage64(ret.first, iv, ret.second);
+       }
+       return SerializeMessage64(scheme, packed);
+}
+
+#ifdef TZ_BACKEND_ENABLED
+RawBuffer pack64TZ(const RawBuffer &keyId,
+                                const Password &pwd,
+                                const RawBuffer &iv,
+                                const RawBuffer &tag)
+{
+       // determine whether the key is password protected and store schema info
+       // we don't need to additionally encrypt key ID
+       int scheme = pwd.empty() ? 0 : 1;
+       if (scheme) {
+               return SerializeMessage64(scheme, keyId, iv, tag);
+       } else {
+               return SerializeMessage64(scheme, keyId);
+       }
 }
+#endif
 
 } // namespace anonymous
 
@@ -234,42 +305,125 @@ POSITIVE_TEST_CASE(Serialization_AliasInfoVector)
        BOOST_REQUIRE(o[1].backend == v[1].backend);
 }
 
-POSITIVE_TEST_CASE(Serialization_32_vs_64_bit)
+POSITIVE_TEST_CASE(Serialization_32_vs_64_bit_SW)
 {
        using Crypto::SW::Store;
 
        // pack 32 -> unpack
-       auto packed = Store::pack(DATA, PASSWORD);
-       auto unpacked = Store::unpack(packed, PASSWORD);
+       auto packed = Store::pack(DATA, "");
+       auto unpacked = Store::unpack(packed, "");
        BOOST_REQUIRE(DATA == unpacked);
 
-       packed = Store::pack(DATA, "");
-       unpacked = Store::unpack(packed, "");
+       packed = Store::pack(DATA, PASSWORD);
+       unpacked = Store::unpack(packed, PASSWORD);
        BOOST_REQUIRE(DATA == unpacked);
 
        // pack 64 -> unpack
-       packed = pack64(DATA);
+       packed = pack64SW(DATA, "");
        unpacked = Store::unpack(packed, "");
        BOOST_REQUIRE(DATA == unpacked);
+
+       packed = pack64SW(DATA, PASSWORD);
+       unpacked = Store::unpack(packed, PASSWORD);
+       BOOST_REQUIRE(DATA == unpacked);
 }
 
-NEGATIVE_TEST_CASE(Serialization_32_vs_64_bit)
+NEGATIVE_TEST_CASE(Serialization_32_vs_64_bit_SW)
 {
        using Crypto::SW::Store;
 
        // pack 32 -> unpack
-       auto packed = Store::pack(DATA, PASSWORD);
+       auto packed = Store::pack(DATA, "");
+
+       BOOST_REQUIRE_THROW(Store::unpack(packed, PASSWORD), Exc::AuthenticationFailed);
+
+       packed = Store::pack(DATA, PASSWORD);
 
        BOOST_REQUIRE_THROW(Store::unpack(packed, "wrong-password"), Exc::AuthenticationFailed);
        BOOST_REQUIRE_THROW(Store::unpack(packed, ""), Exc::AuthenticationFailed);
 
-       packed = Store::pack(DATA, "");
-
+       // pack 64 -> unpack
+       packed = pack64SW(DATA, "");
        BOOST_REQUIRE_THROW(Store::unpack(packed, PASSWORD), Exc::AuthenticationFailed);
 
+       packed = pack64SW(DATA, PASSWORD);
+       BOOST_REQUIRE_THROW(Store::unpack(packed, "wrong-password"), Exc::AuthenticationFailed);
+       BOOST_REQUIRE_THROW(Store::unpack(packed, ""), Exc::AuthenticationFailed);
+}
+
+#ifdef TZ_BACKEND_ENABLED
+POSITIVE_TEST_CASE(Serialization_32_vs_64_bit_TZ)
+{
+       using Crypto::TZ::Store;
+
+       // pack 32 -> unpack
+       RawBuffer keyId(64, 0);
+       RawBuffer tag;
+       Password pass = "test-password";
+       RawBuffer ivNoPass;
+       RawBuffer ivPass = Crypto::TZ::Internals::generateIV();
+       RawBuffer keyIdRet, ivRet, tagRet;
+       int noPassScheme = 0;
+       int passScheme = 1;
+
+       auto packed = Store::pack(keyId, "", ivNoPass, tag);
+       Store::unpack(packed, "", noPassScheme, keyIdRet, ivRet, tagRet);
+       BOOST_REQUIRE(keyId == keyIdRet);
+       BOOST_REQUIRE(ivNoPass == ivRet);
+       BOOST_REQUIRE(tag == tagRet);
+
+       packed = Store::pack(keyId, pass, ivPass, tag);
+       Store::unpack(packed, pass, passScheme, keyIdRet, ivRet, tagRet);
+       BOOST_REQUIRE(keyId == keyIdRet);
+       BOOST_REQUIRE(ivPass == ivRet);
+       BOOST_REQUIRE(tag == tagRet);
+
        // pack 64 -> unpack
-       packed = pack64(DATA);
-       BOOST_REQUIRE_THROW(Store::unpack(packed, PASSWORD), Exc::AuthenticationFailed);
+       RawBuffer keyId64(64, 0);
+       ivRet.clear();
+
+       packed = pack64TZ(keyId64, "", ivNoPass, tag);
+       Store::unpack(packed, "", noPassScheme, keyIdRet, ivRet, tagRet);
+       BOOST_REQUIRE(keyId == keyIdRet);
+       BOOST_REQUIRE(ivNoPass == ivRet);
+       BOOST_REQUIRE(tag == tagRet);
+
+       packed = pack64TZ(keyId64, pass, ivPass, tag);
+       Store::unpack(packed, pass, passScheme, keyIdRet, ivRet, tagRet);
+       BOOST_REQUIRE(keyId == keyIdRet);
+       BOOST_REQUIRE(ivPass == ivRet);
+       BOOST_REQUIRE(tag == tagRet);
+}
+
+NEGATIVE_TEST_CASE(Serialization_32_vs_64_bit_TZ)
+{
+       using Crypto::TZ::Store;
+
+       // pack 32 -> unpack
+       RawBuffer keyId(64, 0);
+       RawBuffer tag;
+       Password pass = "test-password";
+       RawBuffer iv = Crypto::TZ::Internals::generateIV();
+       RawBuffer keyIdRet, ivRet, tagRet;
+       int scheme = 1;
+
+       auto packed = Store::pack(keyId, pass, iv, tag);
+       BOOST_REQUIRE_THROW(Store::unpack(packed, "", scheme, keyIdRet, ivRet, tagRet),
+                                               Exc::AuthenticationFailed);
+
+       packed = Store::pack(keyId, "", iv, tag);
+       BOOST_REQUIRE_THROW(Store::unpack(packed, "wrong-password", scheme, keyIdRet, ivRet, tagRet),
+                                               Exc::AuthenticationFailed);
+
+       // pack 64 -> unpack
+       packed = pack64TZ(keyId, pass, iv, tag);
+       BOOST_REQUIRE_THROW(Store::unpack(packed, "", scheme, keyIdRet, ivRet, tagRet),
+                                               Exc::AuthenticationFailed);
+
+       packed = pack64TZ(keyId, "", iv, tag);
+       BOOST_REQUIRE_THROW(Store::unpack(packed, "wrong-password", scheme, keyIdRet, ivRet, tagRet),
+                                               Exc::AuthenticationFailed);
 }
+#endif
 
 BOOST_AUTO_TEST_SUITE_END()