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