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, signedConfPath); 86 } 87 virtual void TearDown() 88 { 89 command("rm -rf " + std::string(testPath)); 90 } 91 std::unique_ptr<Signature> signature; 92 fs::path extractPath; 93 fs::path signedConfPath; 94 fs::path signedConfPNORPath; 95 }; 96 97 /** @brief Test for success scenario*/ 98 TEST_F(SignatureTest, TestSignatureVerify) 99 { 100 EXPECT_TRUE(signature->verify()); 101 } 102 103 /** @brief Test failure scenario with corrupted signature file*/ 104 TEST_F(SignatureTest, TestCorruptSignatureFile) 105 { 106 // corrupt the image-kernel.sig file and ensure that verification fails 107 std::string kernelFile = extractPath.string() + "/" + "pnor.xz.squashfs"; 108 command("echo \"dummy data\" > " + kernelFile + ".sig "); 109 EXPECT_FALSE(signature->verify()); 110 } 111 112 /** @brief Test failure scenario with no public key in the image*/ 113 TEST_F(SignatureTest, TestNoPublicKeyInImage) 114 { 115 // Remove publickey file from the image and ensure that verify fails 116 std::string pubkeyFile = extractPath.string() + "/" + "publickey"; 117 command("rm " + pubkeyFile); 118 EXPECT_FALSE(signature->verify()); 119 } 120 121 /** @brief Test failure scenario with invalid hash function value*/ 122 TEST_F(SignatureTest, TestInvalidHashValue) 123 { 124 // Change the hashfunc value and ensure that verification fails 125 std::string hashFile = signedConfPNORPath.string() + "/hashfunc"; 126 command("echo \"HashType=md5\" > " + hashFile); 127 EXPECT_FALSE(signature->verify()); 128 } 129 130 /** @brief Test for failure scenario with no config file in system*/ 131 TEST_F(SignatureTest, TestNoConfigFileInSystem) 132 { 133 // Remove the conf folder in the system and ensure that verify fails 134 command("rm -rf " + signedConfPNORPath.string()); 135 EXPECT_FALSE(signature->verify()); 136 } 137