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,