1 #include "image_verify.hpp"
2
3 #include <openssl/sha.h>
4
5 #include <filesystem>
6 #include <string>
7
8 #include <gtest/gtest.h>
9
10 using namespace openpower::software::image;
11
12 class SignatureTest : public testing::Test
13 {
14 static constexpr auto opensslCmd = "openssl dgst -sha256 -sign ";
15 static constexpr auto testPath = "/tmp/_testSig";
16
17 protected:
command(const std::string & cmd)18 void command(const std::string& cmd)
19 {
20 auto val = std::system(cmd.c_str());
21 if (val)
22 {
23 std::cout << "COMMAND Error: " << val << std::endl;
24 }
25 }
SetUp()26 virtual void SetUp()
27 {
28 // Create test base directory.
29 std::filesystem::create_directories(testPath);
30
31 // Create unique temporary path for images.
32 std::string tmpDir(testPath);
33 tmpDir += "/extractXXXXXX";
34 std::string imageDir = mkdtemp(const_cast<char*>(tmpDir.c_str()));
35
36 // Create unique temporary configuration path
37 std::string tmpConfDir(testPath);
38 tmpConfDir += "/confXXXXXX";
39 std::string confDir = mkdtemp(const_cast<char*>(tmpConfDir.c_str()));
40
41 extractPath = imageDir;
42 extractPath /= "images";
43
44 signedConfPath = confDir;
45 signedConfPath /= "conf";
46
47 signedConfPNORPath = confDir;
48 signedConfPNORPath /= "conf";
49 signedConfPNORPath /= "OpenBMC";
50
51 std::cout << "SETUP " << std::endl;
52
53 command("mkdir " + extractPath.string());
54 command("mkdir " + signedConfPath.string());
55 command("mkdir " + signedConfPNORPath.string());
56
57 std::string hashFile = signedConfPNORPath.string() + "/hashfunc";
58 command("echo \"HashType=RSA-SHA256\" > " + hashFile);
59
60 std::string manifestFile = extractPath.string() + "/" + "MANIFEST";
61 command("echo \"HashType=RSA-SHA256\" > " + manifestFile);
62 command("echo \"KeyType=OpenBMC\" >> " + manifestFile);
63
64 std::string pnorFile = extractPath.string() + "/" + "pnor.xz.squashfs";
65 command("echo \"pnor.xz.squashfs file \" > " + pnorFile);
66
67 std::string pkeyFile = extractPath.string() + "/" + "private.pem";
68 command("openssl genrsa -out " + pkeyFile + " 4096");
69
70 std::string pubkeyFile = extractPath.string() + "/" + "publickey";
71 command("openssl rsa -in " + pkeyFile + " -outform PEM " +
72 "-pubout -out " + pubkeyFile);
73
74 std::string pubKeyConfFile =
75 signedConfPNORPath.string() + "/" + "publickey";
76 command("cp " + pubkeyFile + " " + signedConfPNORPath.string());
77 command(opensslCmd + pkeyFile + " -out " + pnorFile + ".sig " +
78 pnorFile);
79
80 command(opensslCmd + pkeyFile + " -out " + manifestFile + ".sig " +
81 manifestFile);
82 command(opensslCmd + pkeyFile + " -out " + pubkeyFile + ".sig " +
83 pubkeyFile);
84
85 signature = std::make_unique<Signature>(extractPath, "pnor.xz.squashfs",
86 signedConfPath);
87 }
TearDown()88 virtual void TearDown()
89 {
90 command("rm -rf " + std::string(testPath));
91 }
92 std::unique_ptr<Signature> signature;
93 std::filesystem::path extractPath;
94 std::filesystem::path signedConfPath;
95 std::filesystem::path signedConfPNORPath;
96 };
97
98 /** @brief Test for success scenario*/
TEST_F(SignatureTest,TestSignatureVerify)99 TEST_F(SignatureTest, TestSignatureVerify)
100 {
101 EXPECT_TRUE(signature->verify());
102 }
103
104 /** @brief Test failure scenario with corrupted signature file*/
TEST_F(SignatureTest,TestCorruptSignatureFile)105 TEST_F(SignatureTest, TestCorruptSignatureFile)
106 {
107 // corrupt the image-kernel.sig file and ensure that verification fails
108 std::string kernelFile = extractPath.string() + "/" + "pnor.xz.squashfs";
109 command("echo \"dummy data\" > " + kernelFile + ".sig ");
110 EXPECT_FALSE(signature->verify());
111 }
112
113 /** @brief Test failure scenario with no public key in the image*/
TEST_F(SignatureTest,TestNoPublicKeyInImage)114 TEST_F(SignatureTest, TestNoPublicKeyInImage)
115 {
116 // Remove publickey file from the image and ensure that verify fails
117 std::string pubkeyFile = extractPath.string() + "/" + "publickey";
118 command("rm " + pubkeyFile);
119 EXPECT_FALSE(signature->verify());
120 }
121
122 /** @brief Test failure scenario with invalid hash function value*/
TEST_F(SignatureTest,TestInvalidHashValue)123 TEST_F(SignatureTest, TestInvalidHashValue)
124 {
125 // Change the hashfunc value and ensure that verification fails
126 std::string hashFile = signedConfPNORPath.string() + "/hashfunc";
127 command("echo \"HashType=md5\" > " + hashFile);
128 EXPECT_FALSE(signature->verify());
129 }
130
131 /** @brief Test for failure scenario with no config file in system*/
TEST_F(SignatureTest,TestNoConfigFileInSystem)132 TEST_F(SignatureTest, TestNoConfigFileInSystem)
133 {
134 // Remove the conf folder in the system and ensure that verify fails
135 command("rm -rf " + signedConfPNORPath.string());
136 EXPECT_FALSE(signature->verify());
137 }
138