Static layout: support image verification

Add support of image verification for static layout PNOR code update.

Tested: Verify the PNOR code update succeeds with valid-signed PNOR;
        and fails with invalid-signed PNOR or a PNOR tarball without
        signature.

Change-Id: I1aafeb4e8e07eaa16c170f33f4f21940f7c9c146
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/activation.cpp b/activation.cpp
index 2c05ea7..b9cd5ba 100644
--- a/activation.cpp
+++ b/activation.cpp
@@ -176,12 +176,13 @@
 }
 
 #ifdef WANT_SIGNATURE_VERIFY
-bool Activation::validateSignature()
+bool Activation::validateSignature(const std::string& pnorFileName)
 {
     using Signature = openpower::software::image::Signature;
     fs::path imageDir(IMG_DIR);
 
-    Signature signature(imageDir / versionId, PNOR_SIGNED_IMAGE_CONF_PATH);
+    Signature signature(imageDir / versionId, pnorFileName,
+                        PNOR_SIGNED_IMAGE_CONF_PATH);
 
     // Validate the signed image.
     if (signature.verify())
diff --git a/activation.hpp b/activation.hpp
index 1fcae61..a9fb347 100644
--- a/activation.hpp
+++ b/activation.hpp
@@ -299,12 +299,14 @@
      *        update process in lab environment by checking the
      *        fieldModeEnabled property.
      *
+     * @param[in] pnorFileName - The PNOR filename in image dir
+     *
      * @return  true if successful signature validation or field
      *          mode is disabled.
      *          false for unsuccessful signature validation or
      *          any internal failure during the mapper call.
      */
-    bool validateSignature();
+    bool validateSignature(const std::string& pnorFileName);
 
     /**
      * @brief Gets the fieldModeEnabled property value.
diff --git a/image_verify.cpp b/image_verify.cpp
index 4ad22d1..4fb2d9c 100644
--- a/image_verify.cpp
+++ b/image_verify.cpp
@@ -31,9 +31,10 @@
 constexpr auto hashFunctionTag = "HashType";
 
 Signature::Signature(const fs::path& imageDirPath,
+                     const std::string& pnorFileName,
                      const fs::path& signedConfPath) :
     imageDirPath(imageDirPath),
-    signedConfPath(signedConfPath)
+    pnorFileName(pnorFileName), signedConfPath(signedConfPath)
 {
     fs::path file(imageDirPath / MANIFEST_FILE);
 
@@ -103,7 +104,7 @@
         // Validate the PNOR image file.
         // Build Image File name
         fs::path file(imageDirPath);
-        file /= squashFSImage;
+        file /= pnorFileName;
 
         // Build Signature File name
         std::string fileName = file.filename();
@@ -115,7 +116,7 @@
         if (valid == false)
         {
             log<level::ERR>("Image file Signature Validation failed",
-                            entry("IMAGE=%s", squashFSImage));
+                            entry("IMAGE=%s", pnorFileName.c_str()));
             return false;
         }
 
diff --git a/image_verify.hpp b/image_verify.hpp
index 31b5742..0aff4b8 100644
--- a/image_verify.hpp
+++ b/image_verify.hpp
@@ -31,9 +31,6 @@
 using EVP_MD_CTX_Ptr =
     std::unique_ptr<EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)>;
 
-// PNOR flash image file name.
-constexpr auto squashFSImage = "pnor.xz.squashfs";
-
 /** @struct CustomFd
  *
  *  RAII wrapper for file descriptor.
@@ -133,7 +130,9 @@
      * @param[in]  signedConfPath - Path of public key
      *                              hash function files
      */
-    Signature(const fs::path& imageDirPath, const fs::path& signedConfPath);
+    explicit Signature(const fs::path& imageDirPath,
+                       const std::string& pnorFileName,
+                       const fs::path& signedConfPath);
 
     /**
      * @brief Image signature verification function.
@@ -205,6 +204,9 @@
     /** @brief Directory where software images are placed*/
     fs::path imageDirPath;
 
+    /** @brief The PNOR file name in imageDirPath */
+    std::string pnorFileName;
+
     /** @brief Path of public key and hash function files */
     fs::path signedConfPath;
 
diff --git a/static/activation_static.cpp b/static/activation_static.cpp
index 193d6b3..19bb19e 100644
--- a/static/activation_static.cpp
+++ b/static/activation_static.cpp
@@ -2,7 +2,6 @@
 
 #include "item_updater.hpp"
 
-#include <filesystem>
 #include <phosphor-logging/log.hpp>
 
 namespace openpower
@@ -11,7 +10,6 @@
 {
 namespace updater
 {
-namespace fs = std::filesystem;
 namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;
 
 using namespace phosphor::logging;
@@ -27,6 +25,36 @@
 
     if (value == softwareServer::Activation::Activations::Activating)
     {
+        fs::path imagePath(IMG_DIR);
+        imagePath /= versionId;
+
+        for (const auto& entry : fs::directory_iterator(imagePath))
+        {
+            if (entry.path().extension() == ".pnor")
+            {
+                pnorFilePath = entry;
+                break;
+            }
+        }
+        if (pnorFilePath.empty())
+        {
+            log<level::ERR>("Unable to find pnor file",
+                            entry("DIR=%s", imagePath.c_str()));
+            ret = softwareServer::Activation::Activations::Failed;
+            goto out;
+        }
+#ifdef WANT_SIGNATURE_VERIFY
+        // Validate the signed image.
+        if (!validateSignature(pnorFilePath.filename()))
+        {
+            // Cleanup
+            activationBlocksTransition.reset(nullptr);
+            activationProgress.reset(nullptr);
+
+            ret = softwareServer::Activation::Activations::Failed;
+            goto out;
+        }
+#endif
         if (parent.freeSpace())
         {
             startActivation();
@@ -42,30 +70,12 @@
         activationProgress.reset(nullptr);
     }
 
+out:
     return softwareServer::Activation::activation(ret);
 }
 
 void ActivationStatic::startActivation()
 {
-    fs::path pnorFile;
-    fs::path imagePath(IMG_DIR);
-    imagePath /= versionId;
-
-    for (const auto& entry : fs::directory_iterator(imagePath))
-    {
-        if (entry.path().extension() == ".pnor")
-        {
-            pnorFile = entry;
-            break;
-        }
-    }
-    if (pnorFile.empty())
-    {
-        log<level::ERR>("Unable to find pnor file",
-                        entry("DIR=%s", imagePath.c_str()));
-        return;
-    }
-
     if (!activationProgress)
     {
         activationProgress = std::make_unique<ActivationProgress>(bus, path);
@@ -82,9 +92,9 @@
     subscribeToSystemdSignals();
 
     log<level::INFO>("Start programming...",
-                     entry("PNOR=%s", pnorFile.c_str()));
+                     entry("PNOR=%s", pnorFilePath.c_str()));
 
-    std::string pnorFileEscaped = pnorFile.string();
+    std::string pnorFileEscaped = pnorFilePath.string();
     // Escape all '/' to '-'
     std::replace(pnorFileEscaped.begin(), pnorFileEscaped.end(), '/', '-');
 
diff --git a/static/activation_static.hpp b/static/activation_static.hpp
index 6fe7138..258a612 100644
--- a/static/activation_static.hpp
+++ b/static/activation_static.hpp
@@ -2,6 +2,8 @@
 
 #include "activation.hpp"
 
+#include <filesystem>
+
 namespace openpower
 {
 namespace software
@@ -9,6 +11,8 @@
 namespace updater
 {
 
+namespace fs = std::filesystem;
+
 /** @class ActivationStatic
  *  @brief Implementation for static PNOR layout
  */
@@ -25,6 +29,8 @@
     void finishActivation() override;
 
     std::string pnorUpdateUnit;
+
+    fs::path pnorFilePath;
 };
 
 } // namespace updater
diff --git a/test/test_signature.cpp b/test/test_signature.cpp
index b199c74..9e8de4b 100644
--- a/test/test_signature.cpp
+++ b/test/test_signature.cpp
@@ -82,7 +82,8 @@
         command(opensslCmd + pkeyFile + " -out " + pubkeyFile + ".sig " +
                 pubkeyFile);
 
-        signature = std::make_unique<Signature>(extractPath, signedConfPath);
+        signature = std::make_unique<Signature>(extractPath, "pnor.xz.squashfs",
+                                                signedConfPath);
     }
     virtual void TearDown()
     {
diff --git a/ubi/activation_ubi.cpp b/ubi/activation_ubi.cpp
index 9ce7085..5c57c4b 100644
--- a/ubi/activation_ubi.cpp
+++ b/ubi/activation_ubi.cpp
@@ -40,7 +40,7 @@
 
 #ifdef WANT_SIGNATURE_VERIFY
             // Validate the signed image.
-            if (!validateSignature())
+            if (!validateSignature(squashFSImage))
             {
                 // Cleanup
                 activationBlocksTransition.reset(nullptr);
diff --git a/ubi/activation_ubi.hpp b/ubi/activation_ubi.hpp
index c0ffa01..a6ef436 100644
--- a/ubi/activation_ubi.hpp
+++ b/ubi/activation_ubi.hpp
@@ -9,6 +9,8 @@
 namespace updater
 {
 
+constexpr auto squashFSImage = "pnor.xz.squashfs";
+
 class RedundancyPriorityUbi : public RedundancyPriority
 {
   public:
diff --git a/ubi/item_updater_ubi.cpp b/ubi/item_updater_ubi.cpp
index 188b0bf..227bc1a 100644
--- a/ubi/item_updater_ubi.cpp
+++ b/ubi/item_updater_ubi.cpp
@@ -30,8 +30,6 @@
 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 using namespace phosphor::logging;
 
-constexpr auto squashFSImage = "pnor.xz.squashfs";
-
 std::unique_ptr<Activation> ItemUpdaterUbi::createActivationObject(
     const std::string& path, const std::string& versionId,
     const std::string& extVersion,