Optimize message serialization 69/240669/5
authorMateusz Cegielka <m.cegielka@samsung.com>
Mon, 10 Aug 2020 11:24:30 +0000 (13:24 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Wed, 2 Sep 2020 08:54:41 +0000 (08:54 +0000)
There is a MessageBuffer class, which stores a list of byte slices as
std::list<std::vector<unsigned char>> and can be used for serializing
structs. Every member calls a Write method, which creates a new vector
and appends it to the list. After the list is built, a vector with an
exactly right size is allocated and the data is copied. Also, the class
contains unnecessary mutable state, because the logic is shared with
streaming deserialization.

I have replaced the serialization methods with a single function, which
serializes all objects twice. The first pass ignores the data and only
computes the message size, which allows the second pass that actually
writes the data to only use a single allocation. The new interface is
also simpler and more robust.

Change-Id: I6091b71083997faf9302ad8549ade467deb23a58

15 files changed:
src/manager/client-async/client-manager-async-impl.cpp
src/manager/client-async/client-manager-async-impl.h
src/manager/client/client-control.cpp
src/manager/client/client-manager-impl.cpp
src/manager/common/message-buffer.cpp
src/manager/common/message-buffer.h
src/manager/crypto/sw-backend/store.cpp
src/manager/crypto/tz-backend/store.cpp
src/manager/service/ckm-logic.cpp
src/manager/service/ckm-service.cpp
src/manager/service/encryption-service.cpp
src/manager/service/ocsp-logic.cpp
unit-tests/test_data-type.cpp
unit-tests/test_pkcs12.cpp
unit-tests/test_serialization.cpp

index 19479f0..ea5aa54 100644 (file)
@@ -252,9 +252,9 @@ void ManagerAsync::Impl::ocspCheck(const ObserverPtr &observer,
                }
 
                m_counter++;
-               auto send = MessageBuffer::Serialize(m_counter, rawCertChain);
+               auto send = SerializeMessage(m_counter, rawCertChain);
 
-               thread()->sendMessage(AsyncRequest(observer, SERVICE_SOCKET_OCSP, send.Pop(),
+               thread()->sendMessage(AsyncRequest(observer, SERVICE_SOCKET_OCSP, std::move(send),
                                                                                   m_counter, 0));
        }, [&observer](int error) {
                observer->ReceivedError(error);
@@ -402,11 +402,11 @@ void ManagerAsync::Impl::crypt(
 
                auto command = static_cast<int>(encryption ?
                        EncryptionCommand::ENCRYPT : EncryptionCommand::DECRYPT);
-               auto send = MessageBuffer::Serialize(command, m_counter, cas,
-                                                                                        helper.getName(), helper.getOwner(), password, input);
+               auto send = SerializeMessage(command, m_counter, cas, helper.getName(), helper.getOwner(),
+                                                                        password, input);
 
                thread()->sendMessage(AsyncRequest(observer, SERVICE_SOCKET_ENCRYPTION,
-                                                                                  send.Pop(), m_counter, command));
+                                                                                  std::move(send), m_counter, command));
        }, [&observer](int error) {
                observer->ReceivedError(error);
        });
index 6fca459..1a836d7 100644 (file)
@@ -160,10 +160,10 @@ private:
        {
                m_counter++; // yes, it changes m_counter argument passed in args
 
-               auto send = MessageBuffer::Serialize(command, args...);
+               auto send = SerializeMessage(command, args...);
                thread()->sendMessage(AsyncRequest(observer,
                                                                                   SERVICE_SOCKET_CKM_STORAGE,
-                                                                                  send.Pop(),
+                                                                                  std::move(send),
                                                                                   m_counter,
                                                                                   command));
        }
index ed59582..d0a4d18 100644 (file)
@@ -46,12 +46,11 @@ public:
                        return CKM_API_ERROR_INPUT_PARAM;
 
                MessageBuffer recv;
-               auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                        (ControlCommand::UNLOCK_USER_KEY),
-                                                                                        user,
-                                                                                        password);
+               auto send = SerializeMessage(static_cast<int>(ControlCommand::UNLOCK_USER_KEY),
+                                                                        user,
+                                                                        password);
 
-               int retCode = m_controlConnection.processRequest(send.Pop(), recv);
+               int retCode = m_controlConnection.processRequest(send, recv);
 
                if (CKM_API_SUCCESS != retCode)
                        return retCode;
@@ -71,10 +70,9 @@ public:
                        return CKM_API_ERROR_INPUT_PARAM;
 
                MessageBuffer recv;
-               auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                        (ControlCommand::LOCK_USER_KEY), user);
+               auto send = SerializeMessage(static_cast<int>(ControlCommand::LOCK_USER_KEY), user);
 
-               int retCode = m_controlConnection.processRequest(send.Pop(), recv);
+               int retCode = m_controlConnection.processRequest(send, recv);
 
                if (CKM_API_SUCCESS != retCode)
                        return retCode;
@@ -94,10 +92,9 @@ public:
                        return CKM_API_ERROR_INPUT_PARAM;
 
                MessageBuffer recv;
-               auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                        (ControlCommand::REMOVE_USER_DATA), user);
+               auto send = SerializeMessage(static_cast<int>(ControlCommand::REMOVE_USER_DATA), user);
 
-               int retCode = m_controlConnection.processRequest(send.Pop(), recv);
+               int retCode = m_controlConnection.processRequest(send, recv);
 
                if (CKM_API_SUCCESS != retCode)
                        return retCode;
@@ -118,13 +115,12 @@ public:
                        return CKM_API_ERROR_INPUT_PARAM;
 
                MessageBuffer recv;
-               auto send = MessageBuffer::Serialize(
-                                               static_cast<int>(ControlCommand::CHANGE_USER_PASSWORD),
-                                               user,
-                                               oldPassword,
-                                               newPassword);
+               auto send = SerializeMessage(static_cast<int>(ControlCommand::CHANGE_USER_PASSWORD),
+                                                                        user,
+                                                                        oldPassword,
+                                                                        newPassword);
 
-               int retCode = m_controlConnection.processRequest(send.Pop(), recv);
+               int retCode = m_controlConnection.processRequest(send, recv);
 
                if (CKM_API_SUCCESS != retCode)
                        return retCode;
@@ -144,12 +140,11 @@ public:
                        return CKM_API_ERROR_INPUT_PARAM;
 
                MessageBuffer recv;
-               auto send = MessageBuffer::Serialize(
-                                               static_cast<int>(ControlCommand::RESET_USER_PASSWORD),
-                                               user,
-                                               newPassword);
+               auto send = SerializeMessage(static_cast<int>(ControlCommand::RESET_USER_PASSWORD),
+                                                                        user,
+                                                                        newPassword);
 
-               int retCode = m_controlConnection.processRequest(send.Pop(), recv);
+               int retCode = m_controlConnection.processRequest(send, recv);
 
                if (CKM_API_SUCCESS != retCode)
                        return retCode;
@@ -169,10 +164,9 @@ public:
                        return CKM_API_ERROR_INPUT_PARAM;
 
                MessageBuffer recv;
-               auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                        (ControlCommand::REMOVE_APP_DATA), owner);
+               auto send = SerializeMessage(static_cast<int>(ControlCommand::REMOVE_APP_DATA), owner);
 
-               int retCode = m_controlConnection.processRequest(send.Pop(), recv);
+               int retCode = m_controlConnection.processRequest(send, recv);
 
                if (CKM_API_SUCCESS != retCode)
                        return retCode;
@@ -189,10 +183,9 @@ public:
                EXCEPTION_GUARD_START_CPPAPI
 
                MessageBuffer recv;
-               auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                        (ControlCommand::UPDATE_CC_MODE));
+               auto send = SerializeMessage(static_cast<int>(ControlCommand::UPDATE_CC_MODE));
 
-               int retCode = m_controlConnection.processRequest(send.Pop(), recv);
+               int retCode = m_controlConnection.processRequest(send, recv);
 
                if (CKM_API_SUCCESS != retCode)
                        return retCode;
@@ -213,15 +206,14 @@ public:
 
                MessageBuffer recv;
                AliasSupport helper(alias);
-               auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                        (ControlCommand::SET_PERMISSION),
-                                                                                        static_cast<int>(user),
-                                                                                        helper.getName(),
-                                                                                        helper.getOwner(),
-                                                                                        accessor,
-                                                                                        permissionMask);
-
-               int retCode = m_controlConnection.processRequest(send.Pop(), recv);
+               auto send = SerializeMessage(static_cast<int>(ControlCommand::SET_PERMISSION),
+                                                                        static_cast<int>(user),
+                                                                        helper.getName(),
+                                                                        helper.getOwner(),
+                                                                        accessor,
+                                                                        permissionMask);
+
+               int retCode = m_controlConnection.processRequest(send, recv);
 
                if (CKM_API_SUCCESS != retCode)
                        return retCode;
index 9eecd5a..3bbdcc3 100644 (file)
@@ -49,14 +49,14 @@ int getCertChain(
        EXCEPTION_GUARD_START_CPPAPI
 
        MessageBuffer recv;
-       auto send = MessageBuffer::Serialize(static_cast<int>(command),
-                                                                                msgId,
-                                                                                certificate->getDER(),
-                                                                                untrustedVector,
-                                                                                trustedVector,
-                                                                                useTrustedSystemCertificates);
+       auto send = SerializeMessage(static_cast<int>(command),
+                                                                msgId,
+                                                                certificate->getDER(),
+                                                                untrustedVector,
+                                                                trustedVector,
+                                                                useTrustedSystemCertificates);
 
-       int retCode = serviceConnection.processRequest(send.Pop(), recv);
+       int retCode = serviceConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -111,15 +111,15 @@ int Manager::Impl::saveBinaryData(
 
        MessageBuffer recv;
        AliasSupport helper(alias);
-       auto send = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
-                                                                                msgId,
-                                                                                dataType,
-                                                                                helper.getName(),
-                                                                                helper.getOwner(),
-                                                                                rawData,
-                                                                                PolicySerializable(policy));
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::SAVE),
+                                                                msgId,
+                                                                dataType,
+                                                                helper.getName(),
+                                                                helper.getOwner(),
+                                                                rawData,
+                                                                PolicySerializable(policy));
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -186,16 +186,15 @@ int Manager::Impl::savePKCS12(
 
        MessageBuffer recv;
        AliasSupport helper(alias);
-       auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                (LogicCommand::SAVE_PKCS12),
-                                                                                msgId,
-                                                                                helper.getName(),
-                                                                                helper.getOwner(),
-                                                                                PKCS12Serializable(*pkcs.get()),
-                                                                                PolicySerializable(keyPolicy),
-                                                                                PolicySerializable(certPolicy));
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::SAVE_PKCS12),
+                                                                msgId,
+                                                                helper.getName(),
+                                                                helper.getOwner(),
+                                                                PKCS12Serializable(*pkcs.get()),
+                                                                PolicySerializable(keyPolicy),
+                                                                PolicySerializable(certPolicy));
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -228,14 +227,14 @@ int Manager::Impl::getPKCS12(const Alias &alias, const Password &keyPass,
 
        MessageBuffer recv;
        AliasSupport helper(alias);
-       auto send = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
-                                                                                msgId,
-                                                                                helper.getName(),
-                                                                                helper.getOwner(),
-                                                                                keyPass,
-                                                                                certPass);
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::GET_PKCS12),
+                                                                msgId,
+                                                                helper.getName(),
+                                                                helper.getOwner(),
+                                                                keyPass,
+                                                                certPass);
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -266,12 +265,12 @@ int Manager::Impl::removeAlias(const Alias &alias)
 
        MessageBuffer recv;
        AliasSupport helper(alias);
-       auto send = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
-                                                                                msgId,
-                                                                                helper.getName(),
-                                                                                helper.getOwner());
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::REMOVE),
+                                                                msgId,
+                                                                helper.getName(),
+                                                                helper.getOwner());
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -303,14 +302,14 @@ int Manager::Impl::getBinaryData(
 
        MessageBuffer recv;
        AliasSupport helper(alias);
-       auto send = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
-                                                                                msgId,
-                                                                                sendDataType,
-                                                                                helper.getName(),
-                                                                                helper.getOwner(),
-                                                                                password);
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::GET),
+                                                                msgId,
+                                                                sendDataType,
+                                                                helper.getName(),
+                                                                helper.getOwner(),
+                                                                password);
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -339,13 +338,13 @@ int Manager::Impl::getBinaryDataEncryptionStatus(const DataType sendDataType,
 
        MessageBuffer recv;
        AliasSupport helper(alias);
-       auto send = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PROTECTION_STATUS),
-                                                                                msgId,
-                                                                                sendDataType,
-                                                                                helper.getName(),
-                                                                                helper.getOwner());
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::GET_PROTECTION_STATUS),
+                                                                msgId,
+                                                                sendDataType,
+                                                                helper.getName(),
+                                                                helper.getOwner());
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -456,11 +455,9 @@ int Manager::Impl::getBinaryDataAliasVectorHelper(DataType dataType,
        int msgId = ++m_counter;
 
        MessageBuffer recv;
-       auto send = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
-                                                                                msgId,
-                                                                                dataType);
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::GET_LIST), msgId, dataType);
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (retCode != CKM_API_SUCCESS)
                return retCode;
@@ -611,15 +608,14 @@ int Manager::Impl::createKeyAES(
 
        MessageBuffer recv;
        AliasSupport aliasHelper(keyAlias);
-       auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                (LogicCommand::CREATE_KEY_AES),
-                                                                                msgId,
-                                                                                static_cast<int>(size),
-                                                                                PolicySerializable(policyKey),
-                                                                                aliasHelper.getName(),
-                                                                                aliasHelper.getOwner());
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::CREATE_KEY_AES),
+                                                                msgId,
+                                                                static_cast<int>(size),
+                                                                PolicySerializable(policyKey),
+                                                                aliasHelper.getName(),
+                                                                aliasHelper.getOwner());
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -678,18 +674,17 @@ int Manager::Impl::createKeyPair(
        MessageBuffer recv;
        AliasSupport privateHelper(privateKeyAlias);
        AliasSupport publicHelper(publicKeyAlias);
-       auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                (LogicCommand::CREATE_KEY_PAIR),
-                                                                                msgId,
-                                                                                CryptoAlgorithmSerializable(keyGenAlgorithm),
-                                                                                PolicySerializable(policyPrivateKey),
-                                                                                PolicySerializable(policyPublicKey),
-                                                                                privateHelper.getName(),
-                                                                                privateHelper.getOwner(),
-                                                                                publicHelper.getName(),
-                                                                                publicHelper.getOwner());
-
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::CREATE_KEY_PAIR),
+                                                                msgId,
+                                                                CryptoAlgorithmSerializable(keyGenAlgorithm),
+                                                                PolicySerializable(policyPrivateKey),
+                                                                PolicySerializable(policyPublicKey),
+                                                                privateHelper.getName(),
+                                                                privateHelper.getOwner(),
+                                                                publicHelper.getName(),
+                                                                publicHelper.getOwner());
+
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -788,16 +783,15 @@ int Manager::Impl::createSignature(
 
        MessageBuffer recv;
        AliasSupport helper(privateKeyAlias);
-       auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                (LogicCommand::CREATE_SIGNATURE),
-                                                                                msgId,
-                                                                                helper.getName(),
-                                                                                helper.getOwner(),
-                                                                                password,
-                                                                                message,
-                                                                                CryptoAlgorithmSerializable(cAlgorithm));
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
+                                                                msgId,
+                                                                helper.getName(),
+                                                                helper.getOwner(),
+                                                                password,
+                                                                message,
+                                                                CryptoAlgorithmSerializable(cAlgorithm));
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -826,17 +820,16 @@ int Manager::Impl::verifySignature(
 
        MessageBuffer recv;
        AliasSupport helper(publicKeyOrCertAlias);
-       auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                (LogicCommand::VERIFY_SIGNATURE),
-                                                                                msgId,
-                                                                                helper.getName(),
-                                                                                helper.getOwner(),
-                                                                                password,
-                                                                                message,
-                                                                                signature,
-                                                                                CryptoAlgorithmSerializable(cAlg));
-
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
+                                                                msgId,
+                                                                helper.getName(),
+                                                                helper.getOwner(),
+                                                                password,
+                                                                message,
+                                                                signature,
+                                                                CryptoAlgorithmSerializable(cAlg));
+
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -871,9 +864,9 @@ int Manager::Impl::ocspCheck(const CertificateShPtrVector &certChain,
                rawCertChain.push_back(e->getDER());
        }
 
-       auto send = MessageBuffer::Serialize(msgId, rawCertChain);
+       auto send = SerializeMessage(msgId, rawCertChain);
 
-       int retCode = m_ocspConnection.processRequest(send.Pop(), recv);
+       int retCode = m_ocspConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -899,15 +892,14 @@ int Manager::Impl::setPermission(const Alias &alias,
 
        MessageBuffer recv;
        AliasSupport helper(alias);
-       auto send = MessageBuffer::Serialize(static_cast<int>
-                                                                                (LogicCommand::SET_PERMISSION),
-                                                                                msgId,
-                                                                                helper.getName(),
-                                                                                helper.getOwner(),
-                                                                                accessor,
-                                                                                permissionMask);
+       auto send = SerializeMessage(static_cast<int>(LogicCommand::SET_PERMISSION),
+                                                                msgId,
+                                                                helper.getName(),
+                                                                helper.getOwner(),
+                                                                accessor,
+                                                                permissionMask);
 
-       int retCode = m_storageConnection.processRequest(send.Pop(), recv);
+       int retCode = m_storageConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -937,15 +929,15 @@ int Manager::Impl::crypt(EncryptionCommand command,
        MessageBuffer recv;
        AliasSupport helper(keyAlias);
        CryptoAlgorithmSerializable cas(algo);
-       auto send = MessageBuffer::Serialize(static_cast<int>(command),
-                                                                                msgId,
-                                                                                cas,
-                                                                                helper.getName(),
-                                                                                helper.getOwner(),
-                                                                                password,
-                                                                                input);
-
-       int retCode = m_encryptionConnection.processRequest(send.Pop(), recv);
+       auto send = SerializeMessage(static_cast<int>(command),
+                                                                msgId,
+                                                                cas,
+                                                                helper.getName(),
+                                                                helper.getOwner(),
+                                                                password,
+                                                                input);
+
+       int retCode = m_encryptionConnection.processRequest(send, recv);
 
        if (CKM_API_SUCCESS != retCode)
                return retCode;
index 0aa2d11..ef1ceb2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2019 Samsung Electronics Co., Ltd. All rights reserved
+ *  Copyright (c) 2000-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *  Contact: Dongsun Lee <ds73.lee@samsung.com>
  *
@@ -25,6 +25,7 @@
 
 #include <message-buffer.h>
 
+#include <exception.h>
 #include <dpl/log/log.h>
 
 namespace CKM {
@@ -34,16 +35,6 @@ void MessageBuffer::Push(const RawBuffer &data)
        m_buffer.AppendCopy(&data[0], data.size());
 }
 
-RawBuffer MessageBuffer::Pop()
-{
-       size_t size = m_buffer.Size();
-       RawBuffer buffer;
-       buffer.resize(size + sizeof(size_t));
-       memcpy(&buffer[0], &size, sizeof(size_t));
-       m_buffer.FlattenConsume(&buffer[sizeof(size_t)], size);
-       return buffer;
-}
-
 bool MessageBuffer::Ready()
 {
        CountBytesLeft();
@@ -71,9 +62,37 @@ void MessageBuffer::Read(size_t num, void *bytes)
        m_bytesLeft -= num;
 }
 
-void MessageBuffer::Write(size_t num, const void *bytes)
+void MessageBuffer::Write(size_t, const void *)
+{
+       ThrowErr(Exc::InternalError, "unexpected IStream::Write call in MessageBuffer");
+}
+
+void MessageSerializer::Sizer::Read(size_t, void*)
+{
+       ThrowErr(Exc::InternalError, "unexpected IStream::Read call in SerializeMessage");
+}
+
+void MessageSerializer::Sizer::Write(size_t num, const void*)
+{
+       m_bytes += num;
+}
+
+MessageSerializer::Writer::Writer(size_t size)
+{
+       m_buffer.reserve(sizeof(size_t) + size);
+       Serializer<size_t>::Serialize(*this, size);
+}
+
+void MessageSerializer::Writer::Read(size_t, void*)
+{
+       ThrowErr(Exc::InternalError, "unexpected IStream::Read call in SerializeMessage");
+}
+
+void MessageSerializer::Writer::Write(size_t num, const void* bytes)
 {
-       m_buffer.AppendCopy(bytes, num);
+       assert(m_buffer.size() + num <= m_buffer.capacity());
+       m_buffer.resize(m_buffer.size() + num);
+       memcpy(&m_buffer[m_buffer.size() - num], bytes, num);
 }
 
 } // namespace CKM
index 7266d12..6f0572a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000-2019 Samsung Electronics Co., Ltd. All rights reserved
+ *  Copyright (c) 2000-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *  Contact: Dongsun Lee <ds73.lee@samsung.com>
  *
@@ -49,23 +49,12 @@ public:
 
        void Push(const RawBuffer &data);
 
-       RawBuffer Pop();
-
        bool Ready();
 
        virtual void Read(size_t num, void *bytes);
 
        virtual void Write(size_t num, const void *bytes);
 
-       // generic serialization
-       template <typename... Args>
-       static MessageBuffer Serialize(const Args &... args)
-       {
-               MessageBuffer buffer;
-               Serializer<Args...>::Serialize(buffer, args...);
-               return buffer;
-       }
-
        // generic deserialization
        template <typename... Args>
        void Deserialize(Args &... args)
@@ -89,6 +78,43 @@ protected:
        CKM::BinaryQueue m_buffer;
 };
 
+class MessageSerializer final {
+       struct COMMON_API Sizer : IStream {
+               void Read(size_t num, void* bytes) override;
+               void Write(size_t num, const void* bytes) override;
+
+               size_t m_bytes = 0;
+       };
+
+       struct COMMON_API Writer : IStream {
+               Writer(size_t size);
+
+               void Read(size_t num, void* bytes) override;
+               void Write(size_t num, const void* bytes) override;
+
+               RawBuffer m_buffer;
+       };
+
+       MessageSerializer() = delete;
+
+public:
+       template <typename... T>
+       static RawBuffer Run(const T&... args)
+       {
+               Sizer sizer;
+               Serializer<T...>::Serialize(sizer, args...);
+               Writer writer(sizer.m_bytes);
+               Serializer<T...>::Serialize(writer, args...);
+               return std::move(writer.m_buffer);
+       }
+};
+
+template <typename... T>
+RawBuffer SerializeMessage(const T&... args)
+{
+       return MessageSerializer::Run(args...);
+}
+
 } // namespace CKM
 
 #endif // _CENT_KEY_MNG_SOCKET_BUFFER_
index 98ae2bf..08891ed 100644 (file)
@@ -136,11 +136,11 @@ RawBuffer pack(const RawBuffer &data, const Password &pass)
 
                // serialization exceptions will be catched as CKM::Exception and will cause
                // CKM_API_ERROR_SERVER_ERROR
-               packed = MessageBuffer::Serialize(ret.first, iv, ret.second).Pop();
+               packed = SerializeMessage(ret.first, iv, ret.second);
        }
 
        // encryption scheme + internal buffer
-       return MessageBuffer::Serialize(scheme, packed).Pop();
+       return SerializeMessage(scheme, packed);
 }
 
 } // namespace anonymous
index 56ca699..3183937 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2015 - 2020 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.
@@ -79,9 +79,9 @@ RawBuffer pack(const RawBuffer &keyId, const Password &pwd,
        int scheme = pwd.empty() ? EncryptionScheme::NONE : EncryptionScheme::PASSWORD;
 
        if (scheme == EncryptionScheme::PASSWORD) {
-               return MessageBuffer::Serialize(scheme, keyId, iv, tag).Pop();
+               return SerializeMessage(scheme, keyId, iv, tag);
        } else {
-               return MessageBuffer::Serialize(scheme, keyId).Pop();
+               return SerializeMessage(scheme, keyId);
        }
 }
 
index 867b527..925a00e 100644 (file)
@@ -214,13 +214,13 @@ RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
        else // do not allow lock/unlock operations for system users
                retCode = CKM_API_ERROR_INPUT_PARAM;
 
-       return MessageBuffer::Serialize(retCode).Pop();
+       return SerializeMessage(retCode);
 }
 
 RawBuffer CKMLogic::updateCCMode()
 {
        m_accessControl.updateCCMode();
-       return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
+       return SerializeMessage(CKM_API_SUCCESS);
 }
 
 RawBuffer CKMLogic::lockUserKey(uid_t user)
@@ -232,7 +232,7 @@ RawBuffer CKMLogic::lockUserKey(uid_t user)
        else // do not allow lock/unlock operations for system users
                retCode = CKM_API_ERROR_INPUT_PARAM;
 
-       return MessageBuffer::Serialize(retCode).Pop();
+       return SerializeMessage(retCode);
 }
 
 RawBuffer CKMLogic::removeUserData(uid_t user)
@@ -246,7 +246,7 @@ RawBuffer CKMLogic::removeUserData(uid_t user)
                ? CKM_API_ERROR_FILE_SYSTEM
                : CKM_API_SUCCESS;
 
-       return MessageBuffer::Serialize(retCode).Pop();
+       return SerializeMessage(retCode);
 }
 
 int CKMLogic::changeUserPasswordHelper(uid_t user,
@@ -279,7 +279,7 @@ RawBuffer CKMLogic::changeUserPassword(
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       return MessageBuffer::Serialize(retCode).Pop();
+       return SerializeMessage(retCode);
 }
 
 int CKMLogic::resetUserPasswordHelper(
@@ -321,7 +321,7 @@ RawBuffer CKMLogic::resetUserPassword(
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       return MessageBuffer::Serialize(retCode).Pop();
+       return SerializeMessage(retCode);
 }
 
 RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
@@ -352,7 +352,7 @@ RawBuffer CKMLogic::removeApplicationData(const ClientId &owner)
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       return MessageBuffer::Serialize(retCode).Pop();
+       return SerializeMessage(retCode);
 }
 
 int CKMLogic::checkSaveConditions(
@@ -523,8 +523,7 @@ RawBuffer CKMLogic::saveData(
        const PolicySerializable &policy)
 {
        int retCode = verifyAndSaveDataHelper(cred, name, explicitOwner, data, policy);
-       auto response = MessageBuffer::Serialize(msgId, retCode, data.type);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode, data.type);
 }
 
 int CKMLogic::extractPKCS12Data(
@@ -608,8 +607,7 @@ RawBuffer CKMLogic::savePKCS12(
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       auto response = MessageBuffer::Serialize(msgId, retCode);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode);
 }
 
 
@@ -691,8 +689,7 @@ RawBuffer CKMLogic::removeData(
                retCode = CKM_API_ERROR_DB_ERROR;
        }
 
-       auto response = MessageBuffer::Serialize(msgId, retCode);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode);
 }
 
 int CKMLogic::readSingleRow(const Name &name,
@@ -965,11 +962,7 @@ RawBuffer CKMLogic::getData(
        if (CKM_API_SUCCESS != retCode)
                rowData.clear();
 
-       auto response = MessageBuffer::Serialize(msgId,
-                                       retCode,
-                                       objDataType,
-                                       rowData);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode, objDataType, rowData);
 }
 
 RawBuffer CKMLogic::getDataProtectionStatus(
@@ -1001,11 +994,7 @@ RawBuffer CKMLogic::getDataProtectionStatus(
                retCode = CKM_API_SUCCESS;
        }
 
-       auto response = MessageBuffer::Serialize(msgId,
-                                       retCode,
-                                       objDataType,
-                                       status);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode, objDataType, status);
 }
 
 int CKMLogic::getPKCS12Helper(
@@ -1094,8 +1083,7 @@ RawBuffer CKMLogic::getPKCS12(
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       auto response = MessageBuffer::Serialize(msgId, retCode, output);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode, output);
 }
 
 int CKMLogic::getDataListHelper(const Credentials &cred,
@@ -1179,11 +1167,7 @@ RawBuffer CKMLogic::getDataList(
                                                           userVector.end());
        }
 
-       auto response = MessageBuffer::Serialize(msgId,
-                                       retCode,
-                                       dataType,
-                                       ownerNameVector);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode, dataType, ownerNameVector);
 }
 
 int CKMLogic::importInitialData(
@@ -1475,7 +1459,7 @@ RawBuffer CKMLogic::createKeyPair(
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       return MessageBuffer::Serialize(msgId, retCode).Pop();
+       return SerializeMessage(msgId, retCode);
 }
 
 RawBuffer CKMLogic::createKeyAES(
@@ -1500,7 +1484,7 @@ RawBuffer CKMLogic::createKeyAES(
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       return MessageBuffer::Serialize(msgId, retCode).Pop();
+       return SerializeMessage(msgId, retCode);
 }
 
 int CKMLogic::readCertificateHelper(
@@ -1663,8 +1647,7 @@ RawBuffer CKMLogic::getCertificateChain(
                LogError("Unknown error.");
        }
 
-       auto response = MessageBuffer::Serialize(msgId, retCode, chainRawVector);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode, chainRawVector);
 }
 
 RawBuffer CKMLogic::getCertificateChain(
@@ -1695,8 +1678,7 @@ RawBuffer CKMLogic::getCertificateChain(
                LogError("Unknown error.");
        }
 
-       auto response = MessageBuffer::Serialize(msgId, retCode, chainRawVector);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode, chainRawVector);
 }
 
 RawBuffer CKMLogic::createSignature(
@@ -1729,8 +1711,7 @@ RawBuffer CKMLogic::createSignature(
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       auto response = MessageBuffer::Serialize(msgId, retCode, signature);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode, signature);
 }
 
 RawBuffer CKMLogic::verifySignature(
@@ -1766,8 +1747,7 @@ RawBuffer CKMLogic::verifySignature(
                retCode = CKM_API_ERROR_SERVER_ERROR;
        }
 
-       auto response = MessageBuffer::Serialize(msgId, retCode);
-       return response.Pop();
+       return SerializeMessage(msgId, retCode);
 }
 
 int CKMLogic::setPermissionHelper(
@@ -1837,7 +1817,7 @@ RawBuffer CKMLogic::setPermission(
                retCode = CKM_API_ERROR_DB_ERROR;
        }
 
-       return MessageBuffer::Serialize(msgID, retCode).Pop();
+       return SerializeMessage(msgID, retCode);
 }
 
 int CKMLogic::loadAppKey(UserData &handle, const ClientId &owner)
index 3e32c2c..a558ead 100644 (file)
@@ -205,7 +205,7 @@ RawBuffer CKMService::ProcessControl(MessageBuffer &buffer, bool allowed)
 
        if (!allowed) {
                LogError("Access denied!");
-               return MessageBuffer::Serialize(CKM_API_ERROR_ACCESS_DENIED).Pop();
+               return SerializeMessage(CKM_API_ERROR_ACCESS_DENIED);
        }
 
        return logicFunc();
index bc4aa2b..843c3f3 100644 (file)
@@ -47,7 +47,7 @@ void EncryptionService::RespondToClient(const CryptoRequest &request,
                                                                                const RawBuffer &data)
 {
        try {
-               RawBuffer response = MessageBuffer::Serialize(request.msgId, retCode, data).Pop();
+               RawBuffer response = SerializeMessage(request.msgId, retCode, data);
                m_serviceManager->Write(request.conn, response);
        } catch (...) {
                LogError("Failed to send response to the client");
index 9861dc0..051ba23 100644 (file)
@@ -113,7 +113,7 @@ RawBuffer OCSPLogic::ocspCheck(int msgId, const RawBufferVector &rawChain,
        if (retCode == CKM_API_SUCCESS)
                ocspStatus = ocsp.verify(certChain);
 
-       return MessageBuffer::Serialize(msgId, retCode, ocspStatus).Pop();
+       return SerializeMessage(msgId, retCode, ocspStatus);
 }
 
 } // namespace CKM
index 0d2ec24..a237d6a 100644 (file)
@@ -44,9 +44,9 @@ NEGATIVE_TEST_CASE(CONSTRUCTOR)
 NEGATIVE_TEST_CASE(SERIALIZATION)
 {
        MessageBuffer msg;
-       msg.Push(MessageBuffer::Serialize(static_cast<int>(DataType::DB_FIRST - 1)).Pop());
+       msg.Push(SerializeMessage(static_cast<int>(DataType::DB_FIRST - 1)));
        BOOST_REQUIRE_THROW(DataType{msg}, Exc::InputParam);
-       msg.Push(MessageBuffer::Serialize(static_cast<int>(DataType::DB_LAST + 1)).Pop());
+       msg.Push(SerializeMessage(static_cast<int>(DataType::DB_LAST + 1)));
        BOOST_REQUIRE_THROW(DataType{msg}, Exc::InputParam);
 }
 
@@ -56,8 +56,7 @@ POSITIVE_TEST_CASE(SERIALIZATION)
                MessageBuffer msg;
                DataType dt;
 
-               BOOST_REQUIRE_NO_THROW(DataType(typeToCheck).Serialize(msg));
-               msg.Push(msg.Pop());
+               BOOST_REQUIRE_NO_THROW(msg.Push(SerializeMessage(DataType(typeToCheck))));
                BOOST_REQUIRE_NO_THROW(dt = DataType{msg});
                BOOST_REQUIRE(dt == typeToCheck);
        };
index bb7b3fe..4a68f3e 100644 (file)
@@ -135,7 +135,7 @@ POSITIVE_TEST_CASE(pkcs12Serializable)
 
        auto checkPkcs = [&](const PKCS12Serializable& ps) {
                MessageBuffer msg;
-               msg.Push(MessageBuffer::Serialize(ps).Pop());
+               msg.Push(SerializeMessage(ps));
                PKCS12Serializable deserialized(msg);
                BOOST_REQUIRE(!deserialized.empty());
 
@@ -171,7 +171,7 @@ NEGATIVE_TEST_CASE(pkcs12Serializable)
 {
        auto checkEmptiness = [](const PKCS12Serializable& ps) {
                MessageBuffer msg;
-               msg.Push(MessageBuffer::Serialize(ps).Pop());
+               msg.Push(SerializeMessage(ps));
                PKCS12Serializable deserialized(msg);
                BOOST_REQUIRE(deserialized.empty());
        };
index 8b7152e..b9b9eed 100644 (file)
@@ -98,8 +98,7 @@ POSITIVE_TEST_CASE(Serialization_CryptoAlgorithm)
 
        CryptoAlgorithmSerializable input(ca);
        CryptoAlgorithmSerializable output;
-       auto msg = MessageBuffer::Serialize(input);
-       RawBuffer buffer = msg.Pop();
+       RawBuffer buffer = SerializeMessage(input);
        MessageBuffer resp;
        resp.Push(buffer);
        resp.Deserialize(output);
@@ -122,8 +121,7 @@ NEGATIVE_TEST_CASE(Serialization_CryptoAlgorithm)
 
        CryptoAlgorithmSerializable input(ca);
        CryptoAlgorithmSerializable output;
-       auto msg = MessageBuffer::Serialize(input);
-       RawBuffer buffer = msg.Pop();
+       RawBuffer buffer = SerializeMessage(input);
        MessageBuffer resp;
        resp.Push(buffer);
        resp.Deserialize(output);
@@ -153,8 +151,7 @@ NEGATIVE_TEST_CASE(Serialization_CryptoAlgorithm_wrong_name)
 
        CryptoAlgorithmSerializable input(ca);
        CryptoAlgorithmSerializable output;
-       auto msg = MessageBuffer::Serialize(input);
-       RawBuffer buffer = msg.Pop();
+       RawBuffer buffer = SerializeMessage(input);
        MessageBuffer resp;
        resp.Push(buffer);
        BOOST_REQUIRE_THROW(resp.Deserialize(output),