Add a SecureBuffer class

SecureBuffer is like SecureString, but a specialization of
std::vector<uint8_t> that cleans up after itself

Tested: Executed various ipmi commands to see that they still work

Change-Id: Ifd255ef682d6e46d981de6a5a294d12f3666698b
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/include/ipmid/message.hpp b/include/ipmid/message.hpp
index 808d96b..8cb9192 100644
--- a/include/ipmid/message.hpp
+++ b/include/ipmid/message.hpp
@@ -21,6 +21,7 @@
 #include <exception>
 #include <ipmid/api-types.hpp>
 #include <ipmid/message/types.hpp>
+#include <ipmid/types.hpp>
 #include <memory>
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/asio/connection.hpp>
@@ -115,7 +116,7 @@
     Payload(Payload&&) = default;
     Payload& operator=(Payload&&) = default;
 
-    explicit Payload(std::vector<uint8_t>&& data) : raw(std::move(data))
+    explicit Payload(SecureBuffer&& data) : raw(std::move(data))
     {
     }
 
@@ -480,7 +481,7 @@
     // partial bytes in the form of bits
     fixed_uint_t<details::bitStreamSize> bitStream;
     size_t bitCount = 0;
-    std::vector<uint8_t> raw;
+    SecureBuffer raw;
     size_t rawIndex = 0;
     bool trailingOk = true;
     bool unpackCheck = false;
@@ -594,8 +595,8 @@
 
     using ptr = std::shared_ptr<Request>;
 
-    explicit Request(Context::ptr context, std::vector<uint8_t>&& d) :
-        payload(std::forward<std::vector<uint8_t>>(d)), ctx(context)
+    explicit Request(Context::ptr context, SecureBuffer&& d) :
+        payload(std::forward<SecureBuffer>(d)), ctx(context)
     {
     }
 
diff --git a/include/ipmid/message/pack.hpp b/include/ipmid/message/pack.hpp
index 598e650..efafd3d 100644
--- a/include/ipmid/message/pack.hpp
+++ b/include/ipmid/message/pack.hpp
@@ -250,6 +250,22 @@
     }
 };
 
+/** @brief Specialization of PackSingle for SecureBuffer */
+template <>
+struct PackSingle<SecureBuffer>
+{
+    static int op(Payload& p, const SecureBuffer& t)
+    {
+        if (p.bitCount != 0)
+        {
+            return 1;
+        }
+        p.raw.reserve(p.raw.size() + t.size());
+        p.raw.insert(p.raw.end(), t.begin(), t.end());
+        return 0;
+    }
+};
+
 /** @brief Specialization of PackSingle for std::string_view */
 template <>
 struct PackSingle<std::string_view>
diff --git a/include/ipmid/message/unpack.hpp b/include/ipmid/message/unpack.hpp
index d9ccba4..4ac4916 100644
--- a/include/ipmid/message/unpack.hpp
+++ b/include/ipmid/message/unpack.hpp
@@ -324,6 +324,20 @@
     }
 };
 
+/** @brief Specialization of UnpackSingle for SecureBuffer */
+template <>
+struct UnpackSingle<SecureBuffer>
+{
+    static int op(Payload& p, SecureBuffer& t)
+    {
+        // copy out the remainder of the message
+        t.reserve(p.raw.size() - p.rawIndex);
+        t.insert(t.begin(), p.raw.begin() + p.rawIndex, p.raw.end());
+        p.rawIndex = p.raw.size();
+        return 0;
+    }
+};
+
 /** @brief Specialization of UnpackSingle for Payload */
 template <>
 struct UnpackSingle<Payload>
diff --git a/include/ipmid/types.hpp b/include/ipmid/types.hpp
index 1705335..9c59ea0 100644
--- a/include/ipmid/types.hpp
+++ b/include/ipmid/types.hpp
@@ -259,13 +259,21 @@
 using SecureString =
     std::basic_string<char, std::char_traits<char>, SecureAllocator<char>>;
 
+using SecureBuffer = std::vector<uint8_t, SecureAllocator<uint8_t>>;
+
 } // namespace ipmi
+
 namespace std
 {
-
 template <>
 inline ipmi::SecureString::~SecureString()
 {
     OPENSSL_cleanse(&((*this)[0]), this->size());
 }
+
+template <>
+inline ipmi::SecureBuffer::~SecureBuffer()
+{
+    OPENSSL_cleanse(&((*this)[0]), this->size());
+}
 } // namespace std