1 #include "image_verify.hpp" 2 3 #include <openssl/sha.h> 4 5 #include <experimental/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: 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 } 26 virtual void SetUp() 27 { 28 // Create test base directory. 29 fs::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 + " 2048"); 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 } 88 virtual void TearDown() 89 { 90 command("rm -rf " + std::string(testPath)); 91 } 92 std::unique_ptr<Signature> signature; 93 fs::path extractPath; 94 fs::path signedConfPath; 95 fs::path signedConfPNORPath; 96 }; 97 98 /** @brief Test for success scenario*/ 99 TEST_F(SignatureTest, TestSignatureVerify) 100 { 101 EXPECT_TRUE(signature->verify()); 102 } 103 104 /** @brief Test failure scenario with corrupted signature file*/ 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*/ 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*/ 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*/ 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