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