xref: /openbmc/phosphor-bmc-code-mgmt/bmc/test/utest.cpp (revision cab87e9cdeeb3e166d6d577511f6be4dc7721aca)
1*cab87e9cSJagpal Singh Gill #include "config.h"
2*cab87e9cSJagpal Singh Gill 
3*cab87e9cSJagpal Singh Gill #include "image_verify.hpp"
4*cab87e9cSJagpal Singh Gill #include "utils.hpp"
5*cab87e9cSJagpal Singh Gill #include "version.hpp"
6*cab87e9cSJagpal Singh Gill 
7*cab87e9cSJagpal Singh Gill #include <openssl/evp.h>
8*cab87e9cSJagpal Singh Gill #include <stdlib.h>
9*cab87e9cSJagpal Singh Gill 
10*cab87e9cSJagpal Singh Gill #include <filesystem>
11*cab87e9cSJagpal Singh Gill #include <fstream>
12*cab87e9cSJagpal Singh Gill #include <iostream>
13*cab87e9cSJagpal Singh Gill #include <sstream>
14*cab87e9cSJagpal Singh Gill #include <string>
15*cab87e9cSJagpal Singh Gill #include <vector>
16*cab87e9cSJagpal Singh Gill 
17*cab87e9cSJagpal Singh Gill #include <gtest/gtest.h>
18*cab87e9cSJagpal Singh Gill 
19*cab87e9cSJagpal Singh Gill using namespace phosphor::software::manager;
20*cab87e9cSJagpal Singh Gill using namespace phosphor::software::image;
21*cab87e9cSJagpal Singh Gill 
22*cab87e9cSJagpal Singh Gill namespace fs = std::filesystem;
23*cab87e9cSJagpal Singh Gill 
24*cab87e9cSJagpal Singh Gill class VersionTest : public testing::Test
25*cab87e9cSJagpal Singh Gill {
26*cab87e9cSJagpal Singh Gill   protected:
SetUp()27*cab87e9cSJagpal Singh Gill     void SetUp() override
28*cab87e9cSJagpal Singh Gill     {
29*cab87e9cSJagpal Singh Gill         char versionDir[] = "./versionXXXXXX";
30*cab87e9cSJagpal Singh Gill         _directory = mkdtemp(versionDir);
31*cab87e9cSJagpal Singh Gill 
32*cab87e9cSJagpal Singh Gill         if (_directory.empty())
33*cab87e9cSJagpal Singh Gill         {
34*cab87e9cSJagpal Singh Gill             throw std::bad_alloc();
35*cab87e9cSJagpal Singh Gill         }
36*cab87e9cSJagpal Singh Gill     }
37*cab87e9cSJagpal Singh Gill 
TearDown()38*cab87e9cSJagpal Singh Gill     void TearDown() override
39*cab87e9cSJagpal Singh Gill     {
40*cab87e9cSJagpal Singh Gill         fs::remove_all(_directory);
41*cab87e9cSJagpal Singh Gill     }
42*cab87e9cSJagpal Singh Gill 
43*cab87e9cSJagpal Singh Gill     std::string _directory;
44*cab87e9cSJagpal Singh Gill };
45*cab87e9cSJagpal Singh Gill 
46*cab87e9cSJagpal Singh Gill /** @brief Make sure we correctly get the version and purpose from getValue()*/
TEST_F(VersionTest,TestGetValue)47*cab87e9cSJagpal Singh Gill TEST_F(VersionTest, TestGetValue)
48*cab87e9cSJagpal Singh Gill {
49*cab87e9cSJagpal Singh Gill     auto manifestFilePath = _directory + "/" + "MANIFEST";
50*cab87e9cSJagpal Singh Gill     auto version = "test-version";
51*cab87e9cSJagpal Singh Gill     auto purpose = "BMC";
52*cab87e9cSJagpal Singh Gill 
53*cab87e9cSJagpal Singh Gill     std::ofstream file;
54*cab87e9cSJagpal Singh Gill     file.open(manifestFilePath, std::ofstream::out);
55*cab87e9cSJagpal Singh Gill     ASSERT_TRUE(file.is_open());
56*cab87e9cSJagpal Singh Gill 
57*cab87e9cSJagpal Singh Gill     file << "version=" << version << "\n";
58*cab87e9cSJagpal Singh Gill     file << "purpose=" << purpose << "\n";
59*cab87e9cSJagpal Singh Gill     file.close();
60*cab87e9cSJagpal Singh Gill 
61*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getValue(manifestFilePath, "version"), version);
62*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getValue(manifestFilePath, "purpose"), purpose);
63*cab87e9cSJagpal Singh Gill }
64*cab87e9cSJagpal Singh Gill 
TEST_F(VersionTest,TestGetRepeatedValue)65*cab87e9cSJagpal Singh Gill TEST_F(VersionTest, TestGetRepeatedValue)
66*cab87e9cSJagpal Singh Gill {
67*cab87e9cSJagpal Singh Gill     auto manifestFilePath = _directory + "/" + "MANIFEST";
68*cab87e9cSJagpal Singh Gill     const std::vector<std::string> names = {"foo.bar", "baz.bim"};
69*cab87e9cSJagpal Singh Gill 
70*cab87e9cSJagpal Singh Gill     std::ofstream file;
71*cab87e9cSJagpal Singh Gill     file.open(manifestFilePath, std::ofstream::out);
72*cab87e9cSJagpal Singh Gill     ASSERT_TRUE(file.is_open());
73*cab87e9cSJagpal Singh Gill 
74*cab87e9cSJagpal Singh Gill     for (const auto& name : names)
75*cab87e9cSJagpal Singh Gill     {
76*cab87e9cSJagpal Singh Gill         file << "CompatibleName=" << name << "\n";
77*cab87e9cSJagpal Singh Gill     }
78*cab87e9cSJagpal Singh Gill     file.close();
79*cab87e9cSJagpal Singh Gill 
80*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getRepeatedValues(manifestFilePath, "CompatibleName"),
81*cab87e9cSJagpal Singh Gill               names);
82*cab87e9cSJagpal Singh Gill }
83*cab87e9cSJagpal Singh Gill 
TEST_F(VersionTest,TestGetValueWithCRLF)84*cab87e9cSJagpal Singh Gill TEST_F(VersionTest, TestGetValueWithCRLF)
85*cab87e9cSJagpal Singh Gill {
86*cab87e9cSJagpal Singh Gill     auto manifestFilePath = _directory + "/" + "MANIFEST";
87*cab87e9cSJagpal Singh Gill     auto version = "test-version";
88*cab87e9cSJagpal Singh Gill     auto purpose = "BMC";
89*cab87e9cSJagpal Singh Gill 
90*cab87e9cSJagpal Singh Gill     std::ofstream file;
91*cab87e9cSJagpal Singh Gill     file.open(manifestFilePath, std::ofstream::out);
92*cab87e9cSJagpal Singh Gill     ASSERT_TRUE(file.is_open());
93*cab87e9cSJagpal Singh Gill 
94*cab87e9cSJagpal Singh Gill     file << "version=" << version << "\r\n";
95*cab87e9cSJagpal Singh Gill     file << "purpose=" << purpose << "\r\n";
96*cab87e9cSJagpal Singh Gill     file.close();
97*cab87e9cSJagpal Singh Gill 
98*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getValue(manifestFilePath, "version"), version);
99*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getValue(manifestFilePath, "purpose"), purpose);
100*cab87e9cSJagpal Singh Gill }
101*cab87e9cSJagpal Singh Gill 
TEST_F(VersionTest,TestGetVersionWithQuotes)102*cab87e9cSJagpal Singh Gill TEST_F(VersionTest, TestGetVersionWithQuotes)
103*cab87e9cSJagpal Singh Gill {
104*cab87e9cSJagpal Singh Gill     auto releasePath = _directory + "/" + "os-release";
105*cab87e9cSJagpal Singh Gill     auto version = "1.2.3-test-version";
106*cab87e9cSJagpal Singh Gill 
107*cab87e9cSJagpal Singh Gill     std::ofstream file;
108*cab87e9cSJagpal Singh Gill     file.open(releasePath, std::ofstream::out);
109*cab87e9cSJagpal Singh Gill     ASSERT_TRUE(file.is_open());
110*cab87e9cSJagpal Singh Gill 
111*cab87e9cSJagpal Singh Gill     file << "VERSION_ID=\"" << version << "\"\n";
112*cab87e9cSJagpal Singh Gill     file.close();
113*cab87e9cSJagpal Singh Gill 
114*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getBMCVersion(releasePath), version);
115*cab87e9cSJagpal Singh Gill }
116*cab87e9cSJagpal Singh Gill 
TEST_F(VersionTest,TestGetVersionWithoutQuotes)117*cab87e9cSJagpal Singh Gill TEST_F(VersionTest, TestGetVersionWithoutQuotes)
118*cab87e9cSJagpal Singh Gill {
119*cab87e9cSJagpal Singh Gill     auto releasePath = _directory + "/" + "os-release";
120*cab87e9cSJagpal Singh Gill     auto version = "9.88.1-test-version";
121*cab87e9cSJagpal Singh Gill 
122*cab87e9cSJagpal Singh Gill     std::ofstream file;
123*cab87e9cSJagpal Singh Gill     file.open(releasePath, std::ofstream::out);
124*cab87e9cSJagpal Singh Gill     ASSERT_TRUE(file.is_open());
125*cab87e9cSJagpal Singh Gill 
126*cab87e9cSJagpal Singh Gill     file << "VERSION_ID=" << version << "\n";
127*cab87e9cSJagpal Singh Gill     file.close();
128*cab87e9cSJagpal Singh Gill 
129*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getBMCVersion(releasePath), version);
130*cab87e9cSJagpal Singh Gill }
131*cab87e9cSJagpal Singh Gill 
132*cab87e9cSJagpal Singh Gill /** @brief Make sure we correctly get the Id from getId()*/
TEST_F(VersionTest,TestGetId)133*cab87e9cSJagpal Singh Gill TEST_F(VersionTest, TestGetId)
134*cab87e9cSJagpal Singh Gill {
135*cab87e9cSJagpal Singh Gill     auto version = "test-id";
136*cab87e9cSJagpal Singh Gill     unsigned char digest[EVP_MAX_MD_SIZE];
137*cab87e9cSJagpal Singh Gill     unsigned int digest_count = 0;
138*cab87e9cSJagpal Singh Gill 
139*cab87e9cSJagpal Singh Gill     EVP_MD_CTX_Ptr ctx(EVP_MD_CTX_new(), &::EVP_MD_CTX_free);
140*cab87e9cSJagpal Singh Gill 
141*cab87e9cSJagpal Singh Gill     EVP_DigestInit(ctx.get(), EVP_sha512());
142*cab87e9cSJagpal Singh Gill     EVP_DigestUpdate(ctx.get(), version, strlen(version));
143*cab87e9cSJagpal Singh Gill     EVP_DigestFinal(ctx.get(), digest, &digest_count);
144*cab87e9cSJagpal Singh Gill 
145*cab87e9cSJagpal Singh Gill     char mdString[EVP_MAX_MD_SIZE * 2 + 1];
146*cab87e9cSJagpal Singh Gill     for (decltype(digest_count) i = 0; i < digest_count; i++)
147*cab87e9cSJagpal Singh Gill     {
148*cab87e9cSJagpal Singh Gill         snprintf(&mdString[static_cast<size_t>(i) * 2], 3, "%02x",
149*cab87e9cSJagpal Singh Gill                  (unsigned int)digest[i]);
150*cab87e9cSJagpal Singh Gill     }
151*cab87e9cSJagpal Singh Gill     std::string hexId = std::string(mdString);
152*cab87e9cSJagpal Singh Gill     hexId = hexId.substr(0, 8);
153*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getId(version), hexId);
154*cab87e9cSJagpal Singh Gill }
155*cab87e9cSJagpal Singh Gill 
TEST_F(VersionTest,TestGetExtendedVersion)156*cab87e9cSJagpal Singh Gill TEST_F(VersionTest, TestGetExtendedVersion)
157*cab87e9cSJagpal Singh Gill {
158*cab87e9cSJagpal Singh Gill     auto releasePath = _directory + "/" + "os-release";
159*cab87e9cSJagpal Singh Gill     auto ExtendedVersion = "9.88.1-test-ExtendedVersion";
160*cab87e9cSJagpal Singh Gill 
161*cab87e9cSJagpal Singh Gill     std::ofstream file;
162*cab87e9cSJagpal Singh Gill     file.open(releasePath, std::ofstream::out);
163*cab87e9cSJagpal Singh Gill     ASSERT_TRUE(file.is_open());
164*cab87e9cSJagpal Singh Gill 
165*cab87e9cSJagpal Singh Gill     file << "EXTENDED_VERSION=" << ExtendedVersion << "\n";
166*cab87e9cSJagpal Singh Gill     file.close();
167*cab87e9cSJagpal Singh Gill 
168*cab87e9cSJagpal Singh Gill     EXPECT_EQ(Version::getBMCExtendedVersion(releasePath), ExtendedVersion);
169*cab87e9cSJagpal Singh Gill }
170*cab87e9cSJagpal Singh Gill 
171*cab87e9cSJagpal Singh Gill class SignatureTest : public testing::Test
172*cab87e9cSJagpal Singh Gill {
173*cab87e9cSJagpal Singh Gill   public:
174*cab87e9cSJagpal Singh Gill     static constexpr auto opensslCmd = "openssl dgst -sha256 -sign ";
175*cab87e9cSJagpal Singh Gill     static constexpr auto testPath = "/tmp/_testSig";
176*cab87e9cSJagpal Singh Gill 
177*cab87e9cSJagpal Singh Gill   protected:
command(const std::string & cmd)178*cab87e9cSJagpal Singh Gill     static void command(const std::string& cmd)
179*cab87e9cSJagpal Singh Gill     {
180*cab87e9cSJagpal Singh Gill         auto val = std::system(cmd.c_str());
181*cab87e9cSJagpal Singh Gill         if (val)
182*cab87e9cSJagpal Singh Gill         {
183*cab87e9cSJagpal Singh Gill             std::cout << "COMMAND Error: " << val << std::endl;
184*cab87e9cSJagpal Singh Gill         }
185*cab87e9cSJagpal Singh Gill     }
SetUp()186*cab87e9cSJagpal Singh Gill     void SetUp() override
187*cab87e9cSJagpal Singh Gill     {
188*cab87e9cSJagpal Singh Gill         // Create test base directory.
189*cab87e9cSJagpal Singh Gill         fs::create_directories(testPath);
190*cab87e9cSJagpal Singh Gill 
191*cab87e9cSJagpal Singh Gill         // Create unique temporary path for images
192*cab87e9cSJagpal Singh Gill         std::string tmpDir(testPath);
193*cab87e9cSJagpal Singh Gill         tmpDir += "/extractXXXXXX";
194*cab87e9cSJagpal Singh Gill         std::string imageDir = mkdtemp(const_cast<char*>(tmpDir.c_str()));
195*cab87e9cSJagpal Singh Gill 
196*cab87e9cSJagpal Singh Gill         // Create unique temporary configuration path
197*cab87e9cSJagpal Singh Gill         std::string tmpConfDir(testPath);
198*cab87e9cSJagpal Singh Gill         tmpConfDir += "/confXXXXXX";
199*cab87e9cSJagpal Singh Gill         std::string confDir = mkdtemp(const_cast<char*>(tmpConfDir.c_str()));
200*cab87e9cSJagpal Singh Gill 
201*cab87e9cSJagpal Singh Gill         extractPath = imageDir;
202*cab87e9cSJagpal Singh Gill         extractPath /= "images";
203*cab87e9cSJagpal Singh Gill 
204*cab87e9cSJagpal Singh Gill         signedConfPath = confDir;
205*cab87e9cSJagpal Singh Gill         signedConfPath /= "conf";
206*cab87e9cSJagpal Singh Gill 
207*cab87e9cSJagpal Singh Gill         signedConfOpenBMCPath = confDir;
208*cab87e9cSJagpal Singh Gill         signedConfOpenBMCPath /= "conf";
209*cab87e9cSJagpal Singh Gill         signedConfOpenBMCPath /= "OpenBMC";
210*cab87e9cSJagpal Singh Gill 
211*cab87e9cSJagpal Singh Gill         std::cout << "SETUP " << std::endl;
212*cab87e9cSJagpal Singh Gill 
213*cab87e9cSJagpal Singh Gill         command("mkdir " + extractPath.string());
214*cab87e9cSJagpal Singh Gill         command("mkdir " + signedConfPath.string());
215*cab87e9cSJagpal Singh Gill         command("mkdir " + signedConfOpenBMCPath.string());
216*cab87e9cSJagpal Singh Gill 
217*cab87e9cSJagpal Singh Gill         std::string hashFile = signedConfOpenBMCPath.string() + "/hashfunc";
218*cab87e9cSJagpal Singh Gill         command("echo \"HashType=RSA-SHA256\" > " + hashFile);
219*cab87e9cSJagpal Singh Gill 
220*cab87e9cSJagpal Singh Gill         std::string manifestFile = extractPath.string() + "/" + "MANIFEST";
221*cab87e9cSJagpal Singh Gill         command(
222*cab87e9cSJagpal Singh Gill             "echo \"purpose=xyz.openbmc_project.Software.Version.VersionPurpose.BMC\" > " +
223*cab87e9cSJagpal Singh Gill             manifestFile);
224*cab87e9cSJagpal Singh Gill         command("echo \"HashType=RSA-SHA256\" >> " + manifestFile);
225*cab87e9cSJagpal Singh Gill         command("echo \"KeyType=OpenBMC\" >> " + manifestFile);
226*cab87e9cSJagpal Singh Gill 
227*cab87e9cSJagpal Singh Gill         std::string kernelFile = extractPath.string() + "/" + "image-kernel";
228*cab87e9cSJagpal Singh Gill         command("echo \"image-kernel file \" > " + kernelFile);
229*cab87e9cSJagpal Singh Gill 
230*cab87e9cSJagpal Singh Gill         std::string rofsFile = extractPath.string() + "/" + "image-rofs";
231*cab87e9cSJagpal Singh Gill         command("echo \"image-rofs file \" > " + rofsFile);
232*cab87e9cSJagpal Singh Gill 
233*cab87e9cSJagpal Singh Gill         std::string rwfsFile = extractPath.string() + "/" + "image-rwfs";
234*cab87e9cSJagpal Singh Gill         command("echo \"image-rwfs file \" > " + rwfsFile);
235*cab87e9cSJagpal Singh Gill 
236*cab87e9cSJagpal Singh Gill         std::string ubootFile = extractPath.string() + "/" + "image-u-boot";
237*cab87e9cSJagpal Singh Gill         command("echo \"image-u-boot file \" > " + ubootFile);
238*cab87e9cSJagpal Singh Gill 
239*cab87e9cSJagpal Singh Gill         std::string pkeyFile = extractPath.string() + "/" + "private.pem";
240*cab87e9cSJagpal Singh Gill         command("openssl genrsa  -out " + pkeyFile + " 4096");
241*cab87e9cSJagpal Singh Gill 
242*cab87e9cSJagpal Singh Gill         std::string pubkeyFile = extractPath.string() + "/" + "publickey";
243*cab87e9cSJagpal Singh Gill         command("openssl rsa -in " + pkeyFile + " -outform PEM " +
244*cab87e9cSJagpal Singh Gill                 "-pubout -out " + pubkeyFile);
245*cab87e9cSJagpal Singh Gill 
246*cab87e9cSJagpal Singh Gill         command("cp " + pubkeyFile + " " + signedConfOpenBMCPath.string());
247*cab87e9cSJagpal Singh Gill         command(opensslCmd + pkeyFile + " -out " + kernelFile + ".sig " +
248*cab87e9cSJagpal Singh Gill                 kernelFile);
249*cab87e9cSJagpal Singh Gill 
250*cab87e9cSJagpal Singh Gill         command(opensslCmd + pkeyFile + " -out " + manifestFile + ".sig " +
251*cab87e9cSJagpal Singh Gill                 manifestFile);
252*cab87e9cSJagpal Singh Gill         command(opensslCmd + pkeyFile + " -out " + rofsFile + ".sig " +
253*cab87e9cSJagpal Singh Gill                 rofsFile);
254*cab87e9cSJagpal Singh Gill         command(opensslCmd + pkeyFile + " -out " + rwfsFile + ".sig " +
255*cab87e9cSJagpal Singh Gill                 rwfsFile);
256*cab87e9cSJagpal Singh Gill         command(opensslCmd + pkeyFile + " -out " + ubootFile + ".sig " +
257*cab87e9cSJagpal Singh Gill                 ubootFile);
258*cab87e9cSJagpal Singh Gill         command(opensslCmd + pkeyFile + " -out " + pubkeyFile + ".sig " +
259*cab87e9cSJagpal Singh Gill                 pubkeyFile);
260*cab87e9cSJagpal Singh Gill 
261*cab87e9cSJagpal Singh Gill #ifdef WANT_SIGNATURE_VERIFY
262*cab87e9cSJagpal Singh Gill         std::string fullFile = extractPath.string() + "/" + "image-full";
263*cab87e9cSJagpal Singh Gill         command("cat " + kernelFile + ".sig " + rofsFile + ".sig " + rwfsFile +
264*cab87e9cSJagpal Singh Gill                 ".sig " + ubootFile + ".sig " + manifestFile + ".sig " +
265*cab87e9cSJagpal Singh Gill                 pubkeyFile + ".sig > " + fullFile);
266*cab87e9cSJagpal Singh Gill         command(opensslCmd + pkeyFile + " -out " + fullFile + ".sig " +
267*cab87e9cSJagpal Singh Gill                 fullFile);
268*cab87e9cSJagpal Singh Gill #endif
269*cab87e9cSJagpal Singh Gill 
270*cab87e9cSJagpal Singh Gill         signature = std::make_unique<Signature>(extractPath, signedConfPath);
271*cab87e9cSJagpal Singh Gill     }
TearDown()272*cab87e9cSJagpal Singh Gill     void TearDown() override
273*cab87e9cSJagpal Singh Gill     {
274*cab87e9cSJagpal Singh Gill         command("rm -rf " + std::string(testPath));
275*cab87e9cSJagpal Singh Gill     }
276*cab87e9cSJagpal Singh Gill 
277*cab87e9cSJagpal Singh Gill     std::unique_ptr<Signature> signature;
278*cab87e9cSJagpal Singh Gill     fs::path extractPath;
279*cab87e9cSJagpal Singh Gill     fs::path signedConfPath;
280*cab87e9cSJagpal Singh Gill     fs::path signedConfOpenBMCPath;
281*cab87e9cSJagpal Singh Gill };
282*cab87e9cSJagpal Singh Gill 
283*cab87e9cSJagpal Singh Gill /** @brief Test for success scenario*/
TEST_F(SignatureTest,TestSignatureVerify)284*cab87e9cSJagpal Singh Gill TEST_F(SignatureTest, TestSignatureVerify)
285*cab87e9cSJagpal Singh Gill {
286*cab87e9cSJagpal Singh Gill     EXPECT_TRUE(signature->verify());
287*cab87e9cSJagpal Singh Gill }
288*cab87e9cSJagpal Singh Gill 
289*cab87e9cSJagpal Singh Gill /** @brief Test failure scenario with corrupted signature file*/
TEST_F(SignatureTest,TestCorruptSignatureFile)290*cab87e9cSJagpal Singh Gill TEST_F(SignatureTest, TestCorruptSignatureFile)
291*cab87e9cSJagpal Singh Gill {
292*cab87e9cSJagpal Singh Gill     // corrupt the image-kernel.sig file and ensure that verification fails
293*cab87e9cSJagpal Singh Gill     std::string kernelFile = extractPath.string() + "/" + "image-kernel";
294*cab87e9cSJagpal Singh Gill     command("echo \"dummy data\" > " + kernelFile + ".sig ");
295*cab87e9cSJagpal Singh Gill     EXPECT_FALSE(signature->verify());
296*cab87e9cSJagpal Singh Gill }
297*cab87e9cSJagpal Singh Gill 
298*cab87e9cSJagpal Singh Gill /** @brief Test failure scenario with no public key in the image*/
TEST_F(SignatureTest,TestNoPublicKeyInImage)299*cab87e9cSJagpal Singh Gill TEST_F(SignatureTest, TestNoPublicKeyInImage)
300*cab87e9cSJagpal Singh Gill {
301*cab87e9cSJagpal Singh Gill     // Remove publickey file from the image and ensure that verify fails
302*cab87e9cSJagpal Singh Gill     std::string pubkeyFile = extractPath.string() + "/" + "publickey";
303*cab87e9cSJagpal Singh Gill     command("rm " + pubkeyFile);
304*cab87e9cSJagpal Singh Gill     EXPECT_FALSE(signature->verify());
305*cab87e9cSJagpal Singh Gill }
306*cab87e9cSJagpal Singh Gill 
307*cab87e9cSJagpal Singh Gill /** @brief Test failure scenario with invalid hash function value*/
TEST_F(SignatureTest,TestInvalidHashValue)308*cab87e9cSJagpal Singh Gill TEST_F(SignatureTest, TestInvalidHashValue)
309*cab87e9cSJagpal Singh Gill {
310*cab87e9cSJagpal Singh Gill     // Change the hashfunc value and ensure that verification fails
311*cab87e9cSJagpal Singh Gill     std::string hashFile = signedConfOpenBMCPath.string() + "/hashfunc";
312*cab87e9cSJagpal Singh Gill     command("echo \"HashType=md5\" > " + hashFile);
313*cab87e9cSJagpal Singh Gill     EXPECT_FALSE(signature->verify());
314*cab87e9cSJagpal Singh Gill }
315*cab87e9cSJagpal Singh Gill 
316*cab87e9cSJagpal Singh Gill /** @brief Test for failure scenario with no config file in system*/
TEST_F(SignatureTest,TestNoConfigFileInSystem)317*cab87e9cSJagpal Singh Gill TEST_F(SignatureTest, TestNoConfigFileInSystem)
318*cab87e9cSJagpal Singh Gill {
319*cab87e9cSJagpal Singh Gill     // Remove the conf folder in the system and ensure that verify fails
320*cab87e9cSJagpal Singh Gill     command("rm -rf " + signedConfOpenBMCPath.string());
321*cab87e9cSJagpal Singh Gill     EXPECT_FALSE(signature->verify());
322*cab87e9cSJagpal Singh Gill }
323*cab87e9cSJagpal Singh Gill 
324*cab87e9cSJagpal Singh Gill #ifdef WANT_SIGNATURE_VERIFY
325*cab87e9cSJagpal Singh Gill /** @brief Test for failure scenario without full verification */
TEST_F(SignatureTest,TestNoFullSignature)326*cab87e9cSJagpal Singh Gill TEST_F(SignatureTest, TestNoFullSignature)
327*cab87e9cSJagpal Singh Gill {
328*cab87e9cSJagpal Singh Gill     // Remove the full signature and ensure that verify fails
329*cab87e9cSJagpal Singh Gill     std::string fullFile = extractPath.string() + "/" + "image-full.sig";
330*cab87e9cSJagpal Singh Gill     command("rm " + fullFile);
331*cab87e9cSJagpal Singh Gill     EXPECT_FALSE(signature->verify());
332*cab87e9cSJagpal Singh Gill }
333*cab87e9cSJagpal Singh Gill 
334*cab87e9cSJagpal Singh Gill /** @brief Test for failure scenario without full verification */
TEST_F(SignatureTest,TestNoFullSignatureForBIOS)335*cab87e9cSJagpal Singh Gill TEST_F(SignatureTest, TestNoFullSignatureForBIOS)
336*cab87e9cSJagpal Singh Gill {
337*cab87e9cSJagpal Singh Gill     // Remove the full signature
338*cab87e9cSJagpal Singh Gill     std::string fullFile = extractPath.string() + "/" + "image-full.sig";
339*cab87e9cSJagpal Singh Gill     command("rm " + fullFile);
340*cab87e9cSJagpal Singh Gill 
341*cab87e9cSJagpal Singh Gill     // Change the purpose to BIOS
342*cab87e9cSJagpal Singh Gill     std::string manifestFile = extractPath.string() + "/" + "MANIFEST";
343*cab87e9cSJagpal Singh Gill     std::string pkeyFile = extractPath.string() + "/" + "private.pem";
344*cab87e9cSJagpal Singh Gill     command("sed -i s/VersionPurpose.BMC/VersionPurpose.BIOS/ " + manifestFile);
345*cab87e9cSJagpal Singh Gill     command(opensslCmd + pkeyFile + " -out " + manifestFile + ".sig " +
346*cab87e9cSJagpal Singh Gill             manifestFile);
347*cab87e9cSJagpal Singh Gill 
348*cab87e9cSJagpal Singh Gill     // Re-create signature object and make sure verify succeed.
349*cab87e9cSJagpal Singh Gill     signature = std::make_unique<Signature>(extractPath, signedConfPath);
350*cab87e9cSJagpal Singh Gill     EXPECT_TRUE(signature->verify());
351*cab87e9cSJagpal Singh Gill }
352*cab87e9cSJagpal Singh Gill #endif
353*cab87e9cSJagpal Singh Gill 
354*cab87e9cSJagpal Singh Gill class FileTest : public testing::Test
355*cab87e9cSJagpal Singh Gill {
356*cab87e9cSJagpal Singh Gill   protected:
readFile(const fs::path & path)357*cab87e9cSJagpal Singh Gill     static std::string readFile(const fs::path& path)
358*cab87e9cSJagpal Singh Gill     {
359*cab87e9cSJagpal Singh Gill         std::ifstream f(path, std::ios::in);
360*cab87e9cSJagpal Singh Gill         if (!f.is_open())
361*cab87e9cSJagpal Singh Gill         {
362*cab87e9cSJagpal Singh Gill             throw "Failed to open file";
363*cab87e9cSJagpal Singh Gill         }
364*cab87e9cSJagpal Singh Gill 
365*cab87e9cSJagpal Singh Gill         auto sz = static_cast<std::streamsize>(fs::file_size(path));
366*cab87e9cSJagpal Singh Gill         std::string result(static_cast<size_t>(sz), '\0');
367*cab87e9cSJagpal Singh Gill         f.read(result.data(), sz);
368*cab87e9cSJagpal Singh Gill 
369*cab87e9cSJagpal Singh Gill         return result;
370*cab87e9cSJagpal Singh Gill     }
371*cab87e9cSJagpal Singh Gill 
command(const std::string & cmd)372*cab87e9cSJagpal Singh Gill     static void command(const std::string& cmd)
373*cab87e9cSJagpal Singh Gill     {
374*cab87e9cSJagpal Singh Gill         auto val = std::system(cmd.c_str());
375*cab87e9cSJagpal Singh Gill         if (val)
376*cab87e9cSJagpal Singh Gill         {
377*cab87e9cSJagpal Singh Gill             std::cout << "COMMAND Error: " << val << std::endl;
378*cab87e9cSJagpal Singh Gill         }
379*cab87e9cSJagpal Singh Gill     }
380*cab87e9cSJagpal Singh Gill 
SetUp()381*cab87e9cSJagpal Singh Gill     void SetUp() override
382*cab87e9cSJagpal Singh Gill     {
383*cab87e9cSJagpal Singh Gill         // Create test base directory.
384*cab87e9cSJagpal Singh Gill         tmpDir = fs::temp_directory_path() / "testFileXXXXXX";
385*cab87e9cSJagpal Singh Gill         if (!mkdtemp(tmpDir.data()))
386*cab87e9cSJagpal Singh Gill         {
387*cab87e9cSJagpal Singh Gill             throw "Failed to create tmp dir";
388*cab87e9cSJagpal Singh Gill         }
389*cab87e9cSJagpal Singh Gill 
390*cab87e9cSJagpal Singh Gill         std::string file1 = tmpDir + "/file1";
391*cab87e9cSJagpal Singh Gill         std::string file2 = tmpDir + "/file2";
392*cab87e9cSJagpal Singh Gill         command("echo \"File Test1\n\n\" > " + file1);
393*cab87e9cSJagpal Singh Gill         command("echo \"FileTe st2\n\nte st2\" > " + file2);
394*cab87e9cSJagpal Singh Gill 
395*cab87e9cSJagpal Singh Gill         srcFiles.push_back(file1);
396*cab87e9cSJagpal Singh Gill         srcFiles.push_back(file2);
397*cab87e9cSJagpal Singh Gill     }
398*cab87e9cSJagpal Singh Gill 
TearDown()399*cab87e9cSJagpal Singh Gill     void TearDown() override
400*cab87e9cSJagpal Singh Gill     {
401*cab87e9cSJagpal Singh Gill         fs::remove_all(tmpDir);
402*cab87e9cSJagpal Singh Gill     }
403*cab87e9cSJagpal Singh Gill 
404*cab87e9cSJagpal Singh Gill     std::vector<std::string> srcFiles;
405*cab87e9cSJagpal Singh Gill     std::string tmpDir;
406*cab87e9cSJagpal Singh Gill };
407*cab87e9cSJagpal Singh Gill 
TEST_F(FileTest,TestMergeFiles)408*cab87e9cSJagpal Singh Gill TEST_F(FileTest, TestMergeFiles)
409*cab87e9cSJagpal Singh Gill {
410*cab87e9cSJagpal Singh Gill     std::string retFile = tmpDir + "/retFile";
411*cab87e9cSJagpal Singh Gill     std::stringstream ss;
412*cab87e9cSJagpal Singh Gill     ss << "cat";
413*cab87e9cSJagpal Singh Gill     for (const auto& file : srcFiles)
414*cab87e9cSJagpal Singh Gill     {
415*cab87e9cSJagpal Singh Gill         ss << " " << file;
416*cab87e9cSJagpal Singh Gill     }
417*cab87e9cSJagpal Singh Gill     ss << " >> " << retFile;
418*cab87e9cSJagpal Singh Gill     std::string catCommand = ss.str();
419*cab87e9cSJagpal Singh Gill     command(catCommand);
420*cab87e9cSJagpal Singh Gill 
421*cab87e9cSJagpal Singh Gill     std::string dstFile = tmpDir + "/dstFile";
422*cab87e9cSJagpal Singh Gill     utils::mergeFiles(srcFiles, dstFile);
423*cab87e9cSJagpal Singh Gill 
424*cab87e9cSJagpal Singh Gill     ASSERT_NE(fs::file_size(retFile), static_cast<uintmax_t>(-1));
425*cab87e9cSJagpal Singh Gill     ASSERT_NE(fs::file_size(dstFile), static_cast<uintmax_t>(-1));
426*cab87e9cSJagpal Singh Gill     ASSERT_EQ(fs::file_size(retFile), fs::file_size(dstFile));
427*cab87e9cSJagpal Singh Gill 
428*cab87e9cSJagpal Singh Gill     std::string ssRetFile = readFile(fs::path(retFile));
429*cab87e9cSJagpal Singh Gill     std::string ssDstFile = readFile(fs::path(dstFile));
430*cab87e9cSJagpal Singh Gill     ASSERT_EQ(ssRetFile, ssDstFile);
431*cab87e9cSJagpal Singh Gill }
432*cab87e9cSJagpal Singh Gill 
TEST(ExecTest,TestConstructArgv)433*cab87e9cSJagpal Singh Gill TEST(ExecTest, TestConstructArgv)
434*cab87e9cSJagpal Singh Gill {
435*cab87e9cSJagpal Singh Gill     auto name = "/bin/ls";
436*cab87e9cSJagpal Singh Gill     auto arg1 = "-a";
437*cab87e9cSJagpal Singh Gill     auto arg2 = "-l";
438*cab87e9cSJagpal Singh Gill     auto arg3 = "-t";
439*cab87e9cSJagpal Singh Gill     auto arg4 = "-rS";
440*cab87e9cSJagpal Singh Gill     auto argV = utils::internal::constructArgv(name, arg1, arg2, arg3, arg4);
441*cab87e9cSJagpal Singh Gill     char** charArray = argV.data();
442*cab87e9cSJagpal Singh Gill     EXPECT_EQ(argV.size(), 6);
443*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[0], name);
444*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[1], arg1);
445*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[2], arg2);
446*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[3], arg3);
447*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[4], arg4);
448*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[5], nullptr);
449*cab87e9cSJagpal Singh Gill 
450*cab87e9cSJagpal Singh Gill     name = "/usr/bin/du";
451*cab87e9cSJagpal Singh Gill     argV = utils::internal::constructArgv(name);
452*cab87e9cSJagpal Singh Gill     charArray = argV.data();
453*cab87e9cSJagpal Singh Gill     EXPECT_EQ(argV.size(), 2);
454*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[0], name);
455*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[1], nullptr);
456*cab87e9cSJagpal Singh Gill 
457*cab87e9cSJagpal Singh Gill     name = "/usr/bin/hexdump";
458*cab87e9cSJagpal Singh Gill     arg1 = "-C";
459*cab87e9cSJagpal Singh Gill     arg2 = "/path/to/filename";
460*cab87e9cSJagpal Singh Gill     argV = utils::internal::constructArgv(name, arg1, arg2);
461*cab87e9cSJagpal Singh Gill     charArray = argV.data();
462*cab87e9cSJagpal Singh Gill     EXPECT_EQ(argV.size(), 4);
463*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[0], name);
464*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[1], arg1);
465*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[2], arg2);
466*cab87e9cSJagpal Singh Gill     EXPECT_EQ(charArray[3], nullptr);
467*cab87e9cSJagpal Singh Gill }
468