From: Jan Wojtkowski Date: Tue, 1 Oct 2024 13:52:33 +0000 (+0200) Subject: Add more 32 to 64bit migration issue tests X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a9f576d00d00ff60d069093696723a04d51ff9de;p=platform%2Fcore%2Fsecurity%2Fkey-manager.git Add more 32 to 64bit migration issue tests Change-Id: Ide0ed57a1c6aa905487b03063eff29c8719be863 --- diff --git a/src/manager/crypto/sw-backend/store.cpp b/src/manager/crypto/sw-backend/store.cpp index f26bf453..d283db09 100644 --- a/src/manager/crypto/sw-backend/store.cpp +++ b/src/manager/crypto/sw-backend/store.cpp @@ -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 Store::packPassword(int &scheme, + RawBuffer &data, + const Password &pass, + RawBuffer &iv) +{ + iv = generateRandIV(); + RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH); + std::pair 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 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 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); diff --git a/src/manager/crypto/sw-backend/store.h b/src/manager/crypto/sw-backend/store.h index fa61e9bf..5f9c3e1f 100644 --- a/src/manager/crypto/sw-backend/store.h +++ b/src/manager/crypto/sw-backend/store.h @@ -44,6 +44,10 @@ public: const RawBuffer &) override; void destroy(const Token &) override {} + static std::pair 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); }; diff --git a/unit-tests/test_serialization.cpp b/unit-tests/test_serialization.cpp index 9b201cce..2272f746 100644 --- a/unit-tests/test_serialization.cpp +++ b/unit-tests/test_serialization.cpp @@ -21,6 +21,9 @@ #include +#include +#include + #include #include @@ -28,6 +31,16 @@ #include #include #include +#include +#ifdef TZ_BACKEND_ENABLED +#include +#include +#endif + +#include +#include + +#include 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::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 + static RawBuffer Run64(const T&... args) + { + Sizer64 sizer; + Serializer::Serialize(sizer, args...); + Writer64 writer(sizer.m_bytes); + Serializer::Serialize(writer, args...); + return std::move(writer.m_buffer); + } +}; + +template +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 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()