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