updater: send hash file contents

Send the hash file contents to the firmware image or tarball can be
verified, for whatever verification process is used by a platform.

Tested: Verified md5sum of /tmp/bmc.sig matches the signature file's
hash on the host.  Sent the contents over P2A.  The implementation uses
the same data pathway for the firmware image and the signature file.

Signed-off-by: Patrick Venture <venture@google.com>
Change-Id: Icbc7fddc4587059004935cf51063797b25f76ad0
diff --git a/test/tools_updater_unittest.cpp b/test/tools_updater_unittest.cpp
index 46546fa..27a3fc4 100644
--- a/test/tools_updater_unittest.cpp
+++ b/test/tools_updater_unittest.cpp
@@ -23,6 +23,7 @@
     std::string firmwareImage = "image.bin";
     std::string signatureFile = "image.sig";
     std::string expectedBlob = "/flash/image";
+    std::string expectedHash = "/flash/hash";
 
     std::vector<std::string> blobList = {expectedBlob};
     ipmiblob::StatResponse statObj;
@@ -50,6 +51,13 @@
                 sendContents(StrEq(firmwareImage.c_str()), Eq(session)))
         .WillOnce(Return(true));
 
+    EXPECT_CALL(blobMock, openBlob(StrEq(expectedHash.c_str()), Eq(supported)))
+        .WillOnce(Return(session));
+
+    EXPECT_CALL(handlerMock,
+                sendContents(StrEq(signatureFile.c_str()), Eq(session)))
+        .WillOnce(Return(true));
+
     updaterMain(&blobMock, &handlerMock, firmwareImage, signatureFile);
 }
 
diff --git a/tools/updater.cpp b/tools/updater.cpp
index d7e5f96..2465945 100644
--- a/tools/updater.cpp
+++ b/tools/updater.cpp
@@ -35,6 +35,7 @@
      * to legacy for now.
      */
     std::string goalFirmware = "/flash/image";
+    std::string hashFilename = "/flash/hash";
 
     /* Get list of blob_ids, check for /flash/image, or /flash/tarball.
      * TODO(venture) the mechanism doesn't care, but the caller of burn_my_bmc
@@ -77,6 +78,9 @@
     }
 
     /* Yay, our data handler is supported. */
+
+    /* Send over the firmware image. */
+    std::fprintf(stderr, "Sending over the firmware image.\n");
     std::uint16_t session;
     try
     {
@@ -91,7 +95,6 @@
                             std::string(b.what()));
     }
 
-    /* Send over the firmware image. */
     if (!handler->sendContents(imagePath, session))
     {
         /* Need to close the session on failure, or it's stuck open (until the
@@ -104,6 +107,28 @@
     blob->closeBlob(session);
 
     /* Send over the hash contents. */
+    std::fprintf(stderr, "Sending over the hash file.\n");
+    try
+    {
+        session = blob->openBlob(
+            hashFilename,
+            static_cast<std::uint16_t>(supported) |
+                static_cast<std::uint16_t>(blobs::OpenFlags::write));
+    }
+    catch (const ipmiblob::BlobException& b)
+    {
+        throw ToolException("blob exception received: " +
+                            std::string(b.what()));
+    }
+
+    if (!handler->sendContents(signaturePath, session))
+    {
+        blob->closeBlob(session);
+        throw ToolException("Failed to send contents of " + signaturePath);
+    }
+
+    blob->closeBlob(session);
+
     /* Trigger the verification. */
     /* Check the verification. */