image-verify: Skip full verify for non-BMC images

The verifyFullImage() only supports verify BMC image, but does not apply
to other images like BIOS.

Skip doing verifyFullImage() for non-BMC images so that it is possible
to do BIOS code update when fieldMode is enabled.

Tested: Verify BIOS update is successful without verification error.
        Add related unit test case and verify it passes.

Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: Id9e72367bd2797f7a61c017b61fb81df1dd4d15c
diff --git a/image_verify.cpp b/image_verify.cpp
index 098ad9d..9551e4e 100644
--- a/image_verify.cpp
+++ b/image_verify.cpp
@@ -44,6 +44,12 @@
 
     keyType = Version::getValue(file, keyTypeTag);
     hashType = Version::getValue(file, hashFunctionTag);
+
+    // Get purpose
+    auto purposeString = Version::getValue(file, "purpose");
+    auto convertedPurpose =
+        sdbusplus::message::convert_from_string<VersionPurpose>(purposeString);
+    purpose = convertedPurpose.value_or(Version::VersionPurpose::Unknown);
 }
 
 AvailableKeyTypes Signature::getAvailableKeyTypesFromSystem() const
@@ -92,6 +98,12 @@
 {
     bool ret = true;
 #ifdef WANT_SIGNATURE_FULL_VERIFY
+    // Only verify full image for BMC
+    if (purpose != VersionPurpose::BMC)
+    {
+        return ret;
+    }
+
     std::vector<std::string> fullImages = {
         fs::path(imageDirPath) / "image-bmc.sig",
         fs::path(imageDirPath) / "image-hostfw.sig",
diff --git a/image_verify.hpp b/image_verify.hpp
index 8cda65c..38129f9 100644
--- a/image_verify.hpp
+++ b/image_verify.hpp
@@ -1,5 +1,6 @@
 #pragma once
 #include "openssl_alloc.hpp"
+#include "version.hpp"
 
 #include <openssl/evp.h>
 #include <openssl/pem.h>
@@ -26,6 +27,8 @@
 using HashFilePath = fs::path;
 using KeyHashPathPair = std::pair<HashFilePath, PublicKeyPath>;
 using AvailableKeyTypes = std::set<Key_t>;
+using VersionPurpose =
+    sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose;
 
 // RAII support for openSSL functions.
 using BIO_MEM_Ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
@@ -218,6 +221,9 @@
     /** @brief Hash type defined in mainfest file */
     Hash_t hashType;
 
+    /** @brief The image purpose */
+    VersionPurpose purpose;
+
     /** @brief Check and Verify the required image files
      *
      * @param[in] filePath - BMC tarball file path
diff --git a/test/utest.cpp b/test/utest.cpp
index 03dbe26..2297b31 100644
--- a/test/utest.cpp
+++ b/test/utest.cpp
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include "image_verify.hpp"
 #include "utils.hpp"
 #include "version.hpp"
@@ -165,6 +167,7 @@
 
 class SignatureTest : public testing::Test
 {
+  public:
     static constexpr auto opensslCmd = "openssl dgst -sha256 -sign ";
     static constexpr auto testPath = "/tmp/_testSig";
 
@@ -212,7 +215,10 @@
         command("echo \"HashType=RSA-SHA256\" > " + hashFile);
 
         std::string manifestFile = extractPath.string() + "/" + "MANIFEST";
-        command("echo \"HashType=RSA-SHA256\" > " + manifestFile);
+        command(
+            "echo \"purpose=xyz.openbmc_project.Software.Version.VersionPurpose.BMC\" > " +
+            manifestFile);
+        command("echo \"HashType=RSA-SHA256\" >> " + manifestFile);
         command("echo \"KeyType=OpenBMC\" >> " + manifestFile);
 
         std::string kernelFile = extractPath.string() + "/" + "image-kernel";
@@ -312,6 +318,36 @@
     EXPECT_FALSE(signature->verify());
 }
 
+#ifdef WANT_SIGNATURE_FULL_VERIFY
+/** @brief Test for failure scenario without full verification */
+TEST_F(SignatureTest, TestNoFullSignature)
+{
+    // Remove the full signature and ensure that verify fails
+    std::string fullFile = extractPath.string() + "/" + "image-full.sig";
+    command("rm " + fullFile);
+    EXPECT_FALSE(signature->verify());
+}
+
+/** @brief Test for failure scenario without full verification */
+TEST_F(SignatureTest, TestNoFullSignatureForBIOS)
+{
+    // Remove the full signature
+    std::string fullFile = extractPath.string() + "/" + "image-full.sig";
+    command("rm " + fullFile);
+
+    // Change the purpose to BIOS
+    std::string manifestFile = extractPath.string() + "/" + "MANIFEST";
+    std::string pkeyFile = extractPath.string() + "/" + "private.pem";
+    command("sed -i s/VersionPurpose.BMC/VersionPurpose.BIOS/ " + manifestFile);
+    command(opensslCmd + pkeyFile + " -out " + manifestFile + ".sig " +
+            manifestFile);
+
+    // Re-create signature object and make sure verify succeed.
+    signature = std::make_unique<Signature>(extractPath, signedConfPath);
+    EXPECT_TRUE(signature->verify());
+}
+#endif
+
 class FileTest : public testing::Test
 {
   protected: