blob: 21fdc289109bfcfb4750bc417c533c03b13393ae [file] [log] [blame]
Gunnar Mills1ea62e12017-03-27 21:49:16 -05001#include <gtest/gtest.h>
Gunnar Mills2a6981b2017-10-15 17:05:18 -05002#include <openssl/sha.h>
3#include <string>
Jayanth Othayoth7ccaa2a2018-03-21 02:14:34 -05004#include <experimental/filesystem>
Gunnar Mills2a6981b2017-10-15 17:05:18 -05005#include "version.hpp"
Jayanth Othayoth7ccaa2a2018-03-21 02:14:34 -05006#include "image_verify.hpp"
Gunnar Mills2a6981b2017-10-15 17:05:18 -05007
8using namespace openpower::software::updater;
Jayanth Othayoth7ccaa2a2018-03-21 02:14:34 -05009using namespace openpower::software::image;
Gunnar Mills2a6981b2017-10-15 17:05:18 -050010
11/** @brief Make sure we correctly get the Id from getId()*/
12TEST(VersionTest, TestGetId)
13{
14 auto version = "test-id";
15 unsigned char digest[SHA512_DIGEST_LENGTH];
16 SHA512_CTX ctx;
17 SHA512_Init(&ctx);
18 SHA512_Update(&ctx, version, strlen(version));
19 SHA512_Final(digest, &ctx);
Adriana Kobylak70dcb632018-02-27 15:46:52 -060020 char mdString[SHA512_DIGEST_LENGTH * 2 + 1];
Gunnar Mills2a6981b2017-10-15 17:05:18 -050021 for (int i = 0; i < SHA512_DIGEST_LENGTH; i++)
22 {
Adriana Kobylak70dcb632018-02-27 15:46:52 -060023 snprintf(&mdString[i * 2], 3, "%02x", (unsigned int)digest[i]);
Gunnar Mills2a6981b2017-10-15 17:05:18 -050024 }
25 std::string hexId = std::string(mdString);
26 hexId = hexId.substr(0, 8);
27 EXPECT_EQ(Version::getId(version), hexId);
28}
Jayanth Othayoth7ccaa2a2018-03-21 02:14:34 -050029
30class SignatureTest : public testing::Test
31{
32 static constexpr auto opensslCmd = "openssl dgst -sha256 -sign ";
33 static constexpr auto testPath = "/tmp/_testSig";
34
35 protected:
36 void command(const std::string& cmd)
37 {
38 auto val = std::system(cmd.c_str());
39 if (val)
40 {
41 std::cout << "COMMAND Error: " << val << std::endl;
42 }
43 }
44 virtual void SetUp()
45 {
46 // Create test base directory.
47 fs::create_directories(testPath);
48
49 // Create unique temporary path for images.
50 std::string tmpDir(testPath);
51 tmpDir += "/extractXXXXXX";
52 std::string imageDir = mkdtemp(const_cast<char*>(tmpDir.c_str()));
53
54 // Create unique temporary configuration path
55 std::string tmpConfDir(testPath);
56 tmpConfDir += "/confXXXXXX";
57 std::string confDir = mkdtemp(const_cast<char*>(tmpConfDir.c_str()));
58
59 extractPath = imageDir;
60 extractPath /= "images";
61
62 signedConfPath = confDir;
63 signedConfPath /= "conf";
64
65 signedConfPNORPath = confDir;
66 signedConfPNORPath /= "conf";
67 signedConfPNORPath /= "OpenBMC";
68
69 std::cout << "SETUP " << std::endl;
70
71 command("mkdir " + extractPath.string());
72 command("mkdir " + signedConfPath.string());
73 command("mkdir " + signedConfPNORPath.string());
74
75 std::string hashFile = signedConfPNORPath.string() + "/hashfunc";
76 command("echo \"HashType=RSA-SHA256\" > " + hashFile);
77
78 std::string manifestFile = extractPath.string() + "/" + "MANIFEST";
79 command("echo \"HashType=RSA-SHA256\" > " + manifestFile);
80 command("echo \"KeyType=OpenBMC\" >> " + manifestFile);
81
82 std::string pnorFile = extractPath.string() + "/" + "pnor.xz.squashfs";
83 command("echo \"pnor.xz.squashfs file \" > " + pnorFile);
84
85 std::string pkeyFile = extractPath.string() + "/" + "private.pem";
86 command("openssl genrsa -out " + pkeyFile + " 2048");
87
88 std::string pubkeyFile = extractPath.string() + "/" + "publickey";
89 command("openssl rsa -in " + pkeyFile + " -outform PEM " +
90 "-pubout -out " + pubkeyFile);
91
92 std::string pubKeyConfFile =
93 signedConfPNORPath.string() + "/" + "publickey";
94 command("cp " + pubkeyFile + " " + signedConfPNORPath.string());
95 command(opensslCmd + pkeyFile + " -out " + pnorFile + ".sig " +
96 pnorFile);
97
98 command(opensslCmd + pkeyFile + " -out " + manifestFile + ".sig " +
99 manifestFile);
100 command(opensslCmd + pkeyFile + " -out " + pubkeyFile + ".sig " +
101 pubkeyFile);
102
103 signature = std::make_unique<Signature>(extractPath, signedConfPath);
104 }
105 virtual void TearDown()
106 {
107 command("rm -rf " + std::string(testPath));
108 }
Jayanth Othayoth7ccaa2a2018-03-21 02:14:34 -0500109 std::unique_ptr<Signature> signature;
110 fs::path extractPath;
111 fs::path signedConfPath;
112 fs::path signedConfPNORPath;
113};
114
115/** @brief Test for sucess scenario*/
116TEST_F(SignatureTest, TestSignatureVerify)
117{
118 EXPECT_TRUE(signature->verify());
119}
Jayanth Othayoth808c40d2018-03-21 06:08:06 -0500120
121/** @brief Test failure scenario with corrupted signature file*/
122TEST_F(SignatureTest, TestCorruptSignatureFile)
123{
124 // corrupt the image-kernel.sig file and ensure that verification fails
125 std::string kernelFile = extractPath.string() + "/" + "pnor.xz.squashfs";
126 command("echo \"dummy data\" > " + kernelFile + ".sig ");
127 EXPECT_FALSE(signature->verify());
128}
129
130/** @brief Test failure scenario with no public key in the image*/
131TEST_F(SignatureTest, TestNoPublicKeyInImage)
132{
133 // Remove publickey file from the image and ensure that verify fails
134 std::string pubkeyFile = extractPath.string() + "/" + "publickey";
135 command("rm " + pubkeyFile);
136 EXPECT_FALSE(signature->verify());
137}
138
139/** @brief Test failure scenario with invalid hash function value*/
140TEST_F(SignatureTest, TestInvalidHashValue)
141{
142 // Change the hashfunc value and ensure that verification fails
143 std::string hashFile = signedConfPNORPath.string() + "/hashfunc";
144 command("echo \"HashType=md5\" > " + hashFile);
145 EXPECT_FALSE(signature->verify());
146}
147
148/** @brief Test for failure scenario with no config file in system*/
149TEST_F(SignatureTest, TestNoConfigFileInSystem)
150{
151 // Remove the conf folder in the system and ensure that verify fails
152 command("rm -rf " + signedConfPNORPath.string());
153 EXPECT_FALSE(signature->verify());
154}