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