blob: 0163bf016131fa95d9e940c05c8ca725a1633245 [file] [log] [blame]
#include "image_verify.hpp"
#include "version.hpp"
#include <openssl/sha.h>
#include <experimental/filesystem>
#include <string>
#include <gtest/gtest.h>
using namespace openpower::software::updater;
using namespace openpower::software::image;
/** @brief Make sure we correctly get the Id from getId()*/
TEST(VersionTest, TestGetId)
{
auto version = "test-id";
unsigned char digest[SHA512_DIGEST_LENGTH];
SHA512_CTX ctx;
SHA512_Init(&ctx);
SHA512_Update(&ctx, version, strlen(version));
SHA512_Final(digest, &ctx);
char mdString[SHA512_DIGEST_LENGTH * 2 + 1];
for (int i = 0; i < SHA512_DIGEST_LENGTH; i++)
{
snprintf(&mdString[i * 2], 3, "%02x", (unsigned int)digest[i]);
}
std::string hexId = std::string(mdString);
hexId = hexId.substr(0, 8);
EXPECT_EQ(Version::getId(version), hexId);
}
class SignatureTest : public testing::Test
{
static constexpr auto opensslCmd = "openssl dgst -sha256 -sign ";
static constexpr auto testPath = "/tmp/_testSig";
protected:
void command(const std::string& cmd)
{
auto val = std::system(cmd.c_str());
if (val)
{
std::cout << "COMMAND Error: " << val << std::endl;
}
}
virtual void SetUp()
{
// Create test base directory.
fs::create_directories(testPath);
// Create unique temporary path for images.
std::string tmpDir(testPath);
tmpDir += "/extractXXXXXX";
std::string imageDir = mkdtemp(const_cast<char*>(tmpDir.c_str()));
// Create unique temporary configuration path
std::string tmpConfDir(testPath);
tmpConfDir += "/confXXXXXX";
std::string confDir = mkdtemp(const_cast<char*>(tmpConfDir.c_str()));
extractPath = imageDir;
extractPath /= "images";
signedConfPath = confDir;
signedConfPath /= "conf";
signedConfPNORPath = confDir;
signedConfPNORPath /= "conf";
signedConfPNORPath /= "OpenBMC";
std::cout << "SETUP " << std::endl;
command("mkdir " + extractPath.string());
command("mkdir " + signedConfPath.string());
command("mkdir " + signedConfPNORPath.string());
std::string hashFile = signedConfPNORPath.string() + "/hashfunc";
command("echo \"HashType=RSA-SHA256\" > " + hashFile);
std::string manifestFile = extractPath.string() + "/" + "MANIFEST";
command("echo \"HashType=RSA-SHA256\" > " + manifestFile);
command("echo \"KeyType=OpenBMC\" >> " + manifestFile);
std::string pnorFile = extractPath.string() + "/" + "pnor.xz.squashfs";
command("echo \"pnor.xz.squashfs file \" > " + pnorFile);
std::string pkeyFile = extractPath.string() + "/" + "private.pem";
command("openssl genrsa -out " + pkeyFile + " 2048");
std::string pubkeyFile = extractPath.string() + "/" + "publickey";
command("openssl rsa -in " + pkeyFile + " -outform PEM " +
"-pubout -out " + pubkeyFile);
std::string pubKeyConfFile =
signedConfPNORPath.string() + "/" + "publickey";
command("cp " + pubkeyFile + " " + signedConfPNORPath.string());
command(opensslCmd + pkeyFile + " -out " + pnorFile + ".sig " +
pnorFile);
command(opensslCmd + pkeyFile + " -out " + manifestFile + ".sig " +
manifestFile);
command(opensslCmd + pkeyFile + " -out " + pubkeyFile + ".sig " +
pubkeyFile);
signature = std::make_unique<Signature>(extractPath, signedConfPath);
}
virtual void TearDown()
{
command("rm -rf " + std::string(testPath));
}
std::unique_ptr<Signature> signature;
fs::path extractPath;
fs::path signedConfPath;
fs::path signedConfPNORPath;
};
/** @brief Test for success scenario*/
TEST_F(SignatureTest, TestSignatureVerify)
{
EXPECT_TRUE(signature->verify());
}
/** @brief Test failure scenario with corrupted signature file*/
TEST_F(SignatureTest, TestCorruptSignatureFile)
{
// corrupt the image-kernel.sig file and ensure that verification fails
std::string kernelFile = extractPath.string() + "/" + "pnor.xz.squashfs";
command("echo \"dummy data\" > " + kernelFile + ".sig ");
EXPECT_FALSE(signature->verify());
}
/** @brief Test failure scenario with no public key in the image*/
TEST_F(SignatureTest, TestNoPublicKeyInImage)
{
// Remove publickey file from the image and ensure that verify fails
std::string pubkeyFile = extractPath.string() + "/" + "publickey";
command("rm " + pubkeyFile);
EXPECT_FALSE(signature->verify());
}
/** @brief Test failure scenario with invalid hash function value*/
TEST_F(SignatureTest, TestInvalidHashValue)
{
// Change the hashfunc value and ensure that verification fails
std::string hashFile = signedConfPNORPath.string() + "/hashfunc";
command("echo \"HashType=md5\" > " + hashFile);
EXPECT_FALSE(signature->verify());
}
/** @brief Test for failure scenario with no config file in system*/
TEST_F(SignatureTest, TestNoConfigFileInSystem)
{
// Remove the conf folder in the system and ensure that verify fails
command("rm -rf " + signedConfPNORPath.string());
EXPECT_FALSE(signature->verify());
}