113bf74e4SMarri Devender Rao #include "config.h"
213bf74e4SMarri Devender Rao 
38841dbd6SMarri Devender Rao #include "certificate.hpp"
4947258dcSMarri Devender Rao #include "certs_manager.hpp"
5947258dcSMarri Devender Rao 
6947258dcSMarri Devender Rao #include <algorithm>
78841dbd6SMarri Devender Rao #include <filesystem>
8947258dcSMarri Devender Rao #include <fstream>
9947258dcSMarri Devender Rao #include <iterator>
10*f4682712SMarri Devender Rao #include <sdeventplus/event.hpp>
11947258dcSMarri Devender Rao #include <string>
1213bf74e4SMarri Devender Rao #include <xyz/openbmc_project/Certs/error.hpp>
13947258dcSMarri Devender Rao #include <xyz/openbmc_project/Common/error.hpp>
14947258dcSMarri Devender Rao 
15947258dcSMarri Devender Rao #include <gtest/gtest.h>
168841dbd6SMarri Devender Rao namespace fs = std::filesystem;
17947258dcSMarri Devender Rao using InternalFailure =
18947258dcSMarri Devender Rao     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
19e6597c5bSMarri Devender Rao using InvalidCertificate =
2013bf74e4SMarri Devender Rao     sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
218841dbd6SMarri Devender Rao using namespace phosphor::certs;
22e6597c5bSMarri Devender Rao 
23ddf64866SMarri Devender Rao /**
24ddf64866SMarri Devender Rao  * Class to generate certificate file and test verification of certificate file
25ddf64866SMarri Devender Rao  */
268841dbd6SMarri Devender Rao class TestCertificates : public ::testing::Test
27947258dcSMarri Devender Rao {
28947258dcSMarri Devender Rao   public:
298841dbd6SMarri Devender Rao     TestCertificates() : bus(sdbusplus::bus::new_default())
30947258dcSMarri Devender Rao     {
31947258dcSMarri Devender Rao     }
32947258dcSMarri Devender Rao     void SetUp() override
33947258dcSMarri Devender Rao     {
34947258dcSMarri Devender Rao         char dirTemplate[] = "/tmp/FakeCerts.XXXXXX";
35947258dcSMarri Devender Rao         auto dirPtr = mkdtemp(dirTemplate);
36947258dcSMarri Devender Rao         if (dirPtr == NULL)
37947258dcSMarri Devender Rao         {
38947258dcSMarri Devender Rao             throw std::bad_alloc();
39947258dcSMarri Devender Rao         }
40947258dcSMarri Devender Rao         certDir = dirPtr;
41947258dcSMarri Devender Rao         certificateFile = "cert.pem";
42*f4682712SMarri Devender Rao         CSRFile = "domain.csr";
43*f4682712SMarri Devender Rao         privateKeyFile = "privkey.pem";
44947258dcSMarri Devender Rao         std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 ";
45947258dcSMarri Devender Rao         cmd += "-keyout cert.pem -out cert.pem -days 3650 ";
46947258dcSMarri Devender Rao         cmd += "-subj "
47947258dcSMarri Devender Rao                "/O=openbmc-project.xyz/CN=localhost"
48947258dcSMarri Devender Rao                " -nodes";
49947258dcSMarri Devender Rao         auto val = std::system(cmd.c_str());
50947258dcSMarri Devender Rao         if (val)
51947258dcSMarri Devender Rao         {
52947258dcSMarri Devender Rao             std::cout << "COMMAND Error: " << val << std::endl;
53947258dcSMarri Devender Rao         }
54947258dcSMarri Devender Rao     }
55947258dcSMarri Devender Rao     void TearDown() override
56947258dcSMarri Devender Rao     {
57947258dcSMarri Devender Rao         fs::remove_all(certDir);
58947258dcSMarri Devender Rao         fs::remove(certificateFile);
59*f4682712SMarri Devender Rao         fs::remove(CSRFile);
60*f4682712SMarri Devender Rao         fs::remove(privateKeyFile);
61947258dcSMarri Devender Rao     }
62947258dcSMarri Devender Rao 
63947258dcSMarri Devender Rao     bool compareFiles(const std::string& file1, const std::string& file2)
64947258dcSMarri Devender Rao     {
65947258dcSMarri Devender Rao         std::ifstream f1(file1, std::ifstream::binary | std::ifstream::ate);
66947258dcSMarri Devender Rao         std::ifstream f2(file2, std::ifstream::binary | std::ifstream::ate);
67947258dcSMarri Devender Rao 
68947258dcSMarri Devender Rao         if (f1.fail() || f2.fail())
69947258dcSMarri Devender Rao         {
70947258dcSMarri Devender Rao             return false; // file problem
71947258dcSMarri Devender Rao         }
72947258dcSMarri Devender Rao 
73947258dcSMarri Devender Rao         if (f1.tellg() != f2.tellg())
74947258dcSMarri Devender Rao         {
75947258dcSMarri Devender Rao             return false; // size mismatch
76947258dcSMarri Devender Rao         }
77947258dcSMarri Devender Rao 
78947258dcSMarri Devender Rao         // seek back to beginning and use std::equal to compare contents
79947258dcSMarri Devender Rao         f1.seekg(0, std::ifstream::beg);
80947258dcSMarri Devender Rao         f2.seekg(0, std::ifstream::beg);
81947258dcSMarri Devender Rao         return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()),
82947258dcSMarri Devender Rao                           std::istreambuf_iterator<char>(),
83947258dcSMarri Devender Rao                           std::istreambuf_iterator<char>(f2.rdbuf()));
84947258dcSMarri Devender Rao     }
85947258dcSMarri Devender Rao 
86947258dcSMarri Devender Rao   protected:
87947258dcSMarri Devender Rao     sdbusplus::bus::bus bus;
88*f4682712SMarri Devender Rao     std::string certificateFile, CSRFile, privateKeyFile;
89947258dcSMarri Devender Rao 
90947258dcSMarri Devender Rao     std::string certDir;
91947258dcSMarri Devender Rao };
92947258dcSMarri Devender Rao 
93947258dcSMarri Devender Rao class MainApp
94947258dcSMarri Devender Rao {
95947258dcSMarri Devender Rao   public:
96*f4682712SMarri Devender Rao     MainApp(phosphor::certs::Manager* manager,
97*f4682712SMarri Devender Rao             phosphor::certs::CSR* csr = nullptr) :
98*f4682712SMarri Devender Rao         manager(manager),
99*f4682712SMarri Devender Rao         csr(csr)
100947258dcSMarri Devender Rao     {
101947258dcSMarri Devender Rao     }
102947258dcSMarri Devender Rao     void install(std::string& path)
103947258dcSMarri Devender Rao     {
104947258dcSMarri Devender Rao         manager->install(path);
105947258dcSMarri Devender Rao     }
1069abfae88SMarri Devender Rao     void delete_()
1079abfae88SMarri Devender Rao     {
1089abfae88SMarri Devender Rao         manager->delete_();
1099abfae88SMarri Devender Rao     }
110*f4682712SMarri Devender Rao 
111*f4682712SMarri Devender Rao     std::string generateCSR(std::vector<std::string> alternativeNames,
112*f4682712SMarri Devender Rao                             std::string challengePassword, std::string city,
113*f4682712SMarri Devender Rao                             std::string commonName, std::string contactPerson,
114*f4682712SMarri Devender Rao                             std::string country, std::string email,
115*f4682712SMarri Devender Rao                             std::string givenName, std::string initials,
116*f4682712SMarri Devender Rao                             int64_t keyBitLength, std::string keyCurveId,
117*f4682712SMarri Devender Rao                             std::string keyPairAlgorithm,
118*f4682712SMarri Devender Rao                             std::vector<std::string> keyUsage,
119*f4682712SMarri Devender Rao                             std::string organization,
120*f4682712SMarri Devender Rao                             std::string organizationalUnit, std::string state,
121*f4682712SMarri Devender Rao                             std::string surname, std::string unstructuredName)
122*f4682712SMarri Devender Rao     {
123*f4682712SMarri Devender Rao         return (manager->generateCSR(
124*f4682712SMarri Devender Rao             alternativeNames, challengePassword, city, commonName,
125*f4682712SMarri Devender Rao             contactPerson, country, email, givenName, initials, keyBitLength,
126*f4682712SMarri Devender Rao             keyCurveId, keyPairAlgorithm, keyUsage, organization,
127*f4682712SMarri Devender Rao             organizationalUnit, state, surname, unstructuredName));
128*f4682712SMarri Devender Rao     }
129*f4682712SMarri Devender Rao     std::string cSR()
130*f4682712SMarri Devender Rao     {
131*f4682712SMarri Devender Rao         return (csr->cSR());
132*f4682712SMarri Devender Rao     }
133947258dcSMarri Devender Rao     phosphor::certs::Manager* manager;
134*f4682712SMarri Devender Rao     phosphor::certs::CSR* csr;
135947258dcSMarri Devender Rao };
136947258dcSMarri Devender Rao 
137947258dcSMarri Devender Rao /** @brief Check if server install routine is invoked for server setup
138947258dcSMarri Devender Rao  */
1398841dbd6SMarri Devender Rao TEST_F(TestCertificates, InvokeServerInstall)
140947258dcSMarri Devender Rao {
141947258dcSMarri Devender Rao     std::string endpoint("https");
1428841dbd6SMarri Devender Rao     std::string unit("");
143947258dcSMarri Devender Rao     std::string type("server");
1448841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
1458841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
1468841dbd6SMarri Devender Rao     UnitsToRestart verifyUnit(unit);
147947258dcSMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1488841dbd6SMarri Devender Rao     Certificate certificate(bus, objPath, type, unit, installPath,
1498f80c35bSMarri Devender Rao                             certificateFile, false);
150947258dcSMarri Devender Rao     EXPECT_TRUE(fs::exists(verifyPath));
151947258dcSMarri Devender Rao }
152947258dcSMarri Devender Rao 
153947258dcSMarri Devender Rao /** @brief Check if client install routine is invoked for client setup
154947258dcSMarri Devender Rao  */
1558841dbd6SMarri Devender Rao TEST_F(TestCertificates, InvokeClientInstall)
156947258dcSMarri Devender Rao {
157947258dcSMarri Devender Rao     std::string endpoint("ldap");
1588841dbd6SMarri Devender Rao     std::string unit("");
1598841dbd6SMarri Devender Rao     std::string type("server");
1608841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
1618841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
1628841dbd6SMarri Devender Rao     UnitsToRestart verifyUnit(unit);
163947258dcSMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1648841dbd6SMarri Devender Rao     Certificate certificate(bus, objPath, type, unit, installPath,
1658f80c35bSMarri Devender Rao                             certificateFile, false);
166b50789ceSJayanth Othayoth     EXPECT_TRUE(fs::exists(verifyPath));
167b50789ceSJayanth Othayoth }
168b50789ceSJayanth Othayoth 
169b50789ceSJayanth Othayoth /** @brief Check if authority install routine is invoked for authority setup
170b50789ceSJayanth Othayoth  */
1718841dbd6SMarri Devender Rao TEST_F(TestCertificates, InvokeAuthorityInstall)
172b50789ceSJayanth Othayoth {
173b50789ceSJayanth Othayoth     std::string endpoint("ldap");
1748841dbd6SMarri Devender Rao     std::string unit("");
175b50789ceSJayanth Othayoth     std::string type("authority");
1768841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
1778841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
1788841dbd6SMarri Devender Rao     UnitsToRestart verifyUnit(unit);
179b50789ceSJayanth Othayoth     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1808841dbd6SMarri Devender Rao     Certificate certificate(bus, objPath, type, unit, installPath,
1818f80c35bSMarri Devender Rao                             certificateFile, false);
182947258dcSMarri Devender Rao     EXPECT_TRUE(fs::exists(verifyPath));
183947258dcSMarri Devender Rao }
184947258dcSMarri Devender Rao 
185947258dcSMarri Devender Rao /** @brief Compare the installed certificate with the copied certificate
186947258dcSMarri Devender Rao  */
1878841dbd6SMarri Devender Rao TEST_F(TestCertificates, CompareInstalledCertificate)
188947258dcSMarri Devender Rao {
189947258dcSMarri Devender Rao     std::string endpoint("ldap");
1908841dbd6SMarri Devender Rao     std::string unit("");
191947258dcSMarri Devender Rao     std::string type("client");
1928841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
1938841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
1948841dbd6SMarri Devender Rao     UnitsToRestart verifyUnit(unit);
195947258dcSMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1968841dbd6SMarri Devender Rao     Certificate certificate(bus, objPath, type, unit, installPath,
1978f80c35bSMarri Devender Rao                             certificateFile, false);
198947258dcSMarri Devender Rao     EXPECT_TRUE(fs::exists(verifyPath));
199947258dcSMarri Devender Rao     EXPECT_TRUE(compareFiles(verifyPath, certificateFile));
200947258dcSMarri Devender Rao }
201e6597c5bSMarri Devender Rao 
202e6597c5bSMarri Devender Rao /** @brief Check if install fails if certificate file is not found
203e6597c5bSMarri Devender Rao  */
2048841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestNoCertificateFile)
205e6597c5bSMarri Devender Rao {
206e6597c5bSMarri Devender Rao     std::string endpoint("ldap");
2078841dbd6SMarri Devender Rao     std::string unit("");
208e6597c5bSMarri Devender Rao     std::string type("client");
2098841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
2108841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
211b50789ceSJayanth Othayoth     std::string verifyUnit(unit);
212e6597c5bSMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
2138841dbd6SMarri Devender Rao     std::string uploadFile = "nofile.pem";
214e6597c5bSMarri Devender Rao     EXPECT_THROW(
215e6597c5bSMarri Devender Rao         {
216e6597c5bSMarri Devender Rao             try
217e6597c5bSMarri Devender Rao             {
2188841dbd6SMarri Devender Rao                 Certificate certificate(bus, objPath, type, unit, installPath,
2198f80c35bSMarri Devender Rao                                         uploadFile, false);
220e6597c5bSMarri Devender Rao             }
221e6597c5bSMarri Devender Rao             catch (const InternalFailure& e)
222e6597c5bSMarri Devender Rao             {
223e6597c5bSMarri Devender Rao                 throw;
224e6597c5bSMarri Devender Rao             }
225e6597c5bSMarri Devender Rao         },
226e6597c5bSMarri Devender Rao         InternalFailure);
227e6597c5bSMarri Devender Rao     EXPECT_FALSE(fs::exists(verifyPath));
228e6597c5bSMarri Devender Rao }
229e6597c5bSMarri Devender Rao 
230e6597c5bSMarri Devender Rao /** @brief Check if install fails if certificate file is empty
231e6597c5bSMarri Devender Rao  */
2328841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestEmptyCertificateFile)
233e6597c5bSMarri Devender Rao {
234e6597c5bSMarri Devender Rao     std::string endpoint("ldap");
2358841dbd6SMarri Devender Rao     std::string unit("");
236e6597c5bSMarri Devender Rao     std::string type("client");
2378841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
2388841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
2398841dbd6SMarri Devender Rao     std::string verifyUnit(unit);
2408841dbd6SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
241ddf64866SMarri Devender Rao     std::string emptyFile("emptycert.pem");
242e6597c5bSMarri Devender Rao     std::ofstream ofs;
243e6597c5bSMarri Devender Rao     ofs.open(emptyFile, std::ofstream::out);
244e6597c5bSMarri Devender Rao     ofs.close();
245e6597c5bSMarri Devender Rao     EXPECT_THROW(
246e6597c5bSMarri Devender Rao         {
247e6597c5bSMarri Devender Rao             try
248e6597c5bSMarri Devender Rao             {
2498841dbd6SMarri Devender Rao                 Certificate certificate(bus, objPath, type, unit, installPath,
2508f80c35bSMarri Devender Rao                                         emptyFile, false);
251e6597c5bSMarri Devender Rao             }
252e6597c5bSMarri Devender Rao             catch (const InvalidCertificate& e)
253e6597c5bSMarri Devender Rao             {
254e6597c5bSMarri Devender Rao                 throw;
255e6597c5bSMarri Devender Rao             }
256e6597c5bSMarri Devender Rao         },
257e6597c5bSMarri Devender Rao         InvalidCertificate);
258e6597c5bSMarri Devender Rao     EXPECT_FALSE(fs::exists(verifyPath));
259e6597c5bSMarri Devender Rao     fs::remove(emptyFile);
260e6597c5bSMarri Devender Rao }
261e6597c5bSMarri Devender Rao 
262ddf64866SMarri Devender Rao /** @brief Check if install fails if certificate file is corrupted
263e6597c5bSMarri Devender Rao  */
2648841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestInvalidCertificateFile)
265e6597c5bSMarri Devender Rao {
266e6597c5bSMarri Devender Rao     std::string endpoint("ldap");
2678841dbd6SMarri Devender Rao     std::string unit("");
268e6597c5bSMarri Devender Rao     std::string type("client");
269e6597c5bSMarri Devender Rao 
270e6597c5bSMarri Devender Rao     std::ofstream ofs;
271ddf64866SMarri Devender Rao     ofs.open(certificateFile, std::ofstream::out);
272ddf64866SMarri Devender Rao     ofs << "-----BEGIN CERTIFICATE-----";
273ddf64866SMarri Devender Rao     ofs << "ADD_SOME_INVALID_DATA_INTO_FILE";
274ddf64866SMarri Devender Rao     ofs << "-----END CERTIFICATE-----";
275e6597c5bSMarri Devender Rao     ofs.close();
276e6597c5bSMarri Devender Rao 
2778841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
2788841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
279b50789ceSJayanth Othayoth     std::string verifyUnit(unit);
280e6597c5bSMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
281e6597c5bSMarri Devender Rao     EXPECT_THROW(
282e6597c5bSMarri Devender Rao         {
283e6597c5bSMarri Devender Rao             try
284e6597c5bSMarri Devender Rao             {
2858841dbd6SMarri Devender Rao                 Certificate certificate(bus, objPath, type, unit, installPath,
2868f80c35bSMarri Devender Rao                                         certificateFile, false);
287e6597c5bSMarri Devender Rao             }
288e6597c5bSMarri Devender Rao             catch (const InvalidCertificate& e)
289e6597c5bSMarri Devender Rao             {
290e6597c5bSMarri Devender Rao                 throw;
291e6597c5bSMarri Devender Rao             }
292e6597c5bSMarri Devender Rao         },
293e6597c5bSMarri Devender Rao         InvalidCertificate);
294e6597c5bSMarri Devender Rao     EXPECT_FALSE(fs::exists(verifyPath));
295ddf64866SMarri Devender Rao }
296ddf64866SMarri Devender Rao 
2978841dbd6SMarri Devender Rao /** @brief check certificate delete at manager level
2988841dbd6SMarri Devender Rao  */
2998841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestCertManagerDelete)
3009abfae88SMarri Devender Rao {
3019abfae88SMarri Devender Rao     std::string endpoint("ldap");
3028841dbd6SMarri Devender Rao     std::string unit("");
3039abfae88SMarri Devender Rao     std::string type("client");
3048841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
3058841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
3069abfae88SMarri Devender Rao     std::string verifyUnit(unit);
307*f4682712SMarri Devender Rao     // Get default event loop
3089abfae88SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
309*f4682712SMarri Devender Rao     auto event = sdeventplus::Event::get_default();
310*f4682712SMarri Devender Rao     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
3118841dbd6SMarri Devender Rao                     std::move(installPath));
3129abfae88SMarri Devender Rao     MainApp mainApp(&manager);
3139abfae88SMarri Devender Rao     // delete certificate file and verify file is deleted
3149abfae88SMarri Devender Rao     mainApp.delete_();
3159abfae88SMarri Devender Rao     EXPECT_FALSE(fs::exists(verifyPath));
3168841dbd6SMarri Devender Rao }
3178841dbd6SMarri Devender Rao 
3188841dbd6SMarri Devender Rao /** @brief check certificate install at manager level
3196ceec40bSMarri Devender Rao  */
3208841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestCertManagerInstall)
3218841dbd6SMarri Devender Rao {
3228841dbd6SMarri Devender Rao     std::string endpoint("ldap");
3238841dbd6SMarri Devender Rao     std::string unit("");
3248841dbd6SMarri Devender Rao     std::string type("client");
3258841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
3268841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
3278841dbd6SMarri Devender Rao     std::string verifyUnit(unit);
3288841dbd6SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
329*f4682712SMarri Devender Rao     auto event = sdeventplus::Event::get_default();
330*f4682712SMarri Devender Rao     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
3318841dbd6SMarri Devender Rao                     std::move(installPath));
3328841dbd6SMarri Devender Rao     MainApp mainApp(&manager);
3338841dbd6SMarri Devender Rao     mainApp.install(certificateFile);
3348841dbd6SMarri Devender Rao     EXPECT_TRUE(fs::exists(verifyPath));
3359abfae88SMarri Devender Rao }
3369abfae88SMarri Devender Rao 
337ddf64866SMarri Devender Rao /**
338ddf64866SMarri Devender Rao  * Class to generate private and certificate only file and test verification
339ddf64866SMarri Devender Rao  */
3408841dbd6SMarri Devender Rao class TestInvalidCertificate : public ::testing::Test
341ddf64866SMarri Devender Rao {
342ddf64866SMarri Devender Rao   public:
3438841dbd6SMarri Devender Rao     TestInvalidCertificate() : bus(sdbusplus::bus::new_default())
344ddf64866SMarri Devender Rao     {
345ddf64866SMarri Devender Rao     }
346ddf64866SMarri Devender Rao     void SetUp() override
347ddf64866SMarri Devender Rao     {
348ddf64866SMarri Devender Rao         char dirTemplate[] = "/tmp/FakeCerts.XXXXXX";
349ddf64866SMarri Devender Rao         auto dirPtr = mkdtemp(dirTemplate);
350ddf64866SMarri Devender Rao         if (dirPtr == NULL)
351ddf64866SMarri Devender Rao         {
352ddf64866SMarri Devender Rao             throw std::bad_alloc();
353ddf64866SMarri Devender Rao         }
354ddf64866SMarri Devender Rao         certDir = dirPtr;
355ddf64866SMarri Devender Rao         certificateFile = "cert.pem";
356ddf64866SMarri Devender Rao         keyFile = "key.pem";
357ddf64866SMarri Devender Rao         std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 ";
358ddf64866SMarri Devender Rao         cmd += "-keyout key.pem -out cert.pem -days 3650 ";
359ddf64866SMarri Devender Rao         cmd += "-subj "
360ddf64866SMarri Devender Rao                "/O=openbmc-project.xyz/CN=localhost"
361ddf64866SMarri Devender Rao                " -nodes";
362ddf64866SMarri Devender Rao 
363ddf64866SMarri Devender Rao         auto val = std::system(cmd.c_str());
364ddf64866SMarri Devender Rao         if (val)
365ddf64866SMarri Devender Rao         {
366ddf64866SMarri Devender Rao             std::cout << "command Error: " << val << std::endl;
367ddf64866SMarri Devender Rao         }
368ddf64866SMarri Devender Rao     }
369ddf64866SMarri Devender Rao     void TearDown() override
370ddf64866SMarri Devender Rao     {
371ddf64866SMarri Devender Rao         fs::remove_all(certDir);
372ddf64866SMarri Devender Rao         fs::remove(certificateFile);
373ddf64866SMarri Devender Rao         fs::remove(keyFile);
374ddf64866SMarri Devender Rao     }
375ddf64866SMarri Devender Rao 
376ddf64866SMarri Devender Rao   protected:
377ddf64866SMarri Devender Rao     sdbusplus::bus::bus bus;
378ddf64866SMarri Devender Rao     std::string certificateFile;
379ddf64866SMarri Devender Rao     std::string keyFile;
380ddf64866SMarri Devender Rao     std::string certDir;
381ddf64866SMarri Devender Rao };
382ddf64866SMarri Devender Rao 
383ddf64866SMarri Devender Rao /** @brief Check install fails if private key is missing in certificate file
384ddf64866SMarri Devender Rao  */
3858841dbd6SMarri Devender Rao TEST_F(TestInvalidCertificate, TestMissingPrivateKey)
386ddf64866SMarri Devender Rao {
387ddf64866SMarri Devender Rao     std::string endpoint("ldap");
3888841dbd6SMarri Devender Rao     std::string unit("");
389ddf64866SMarri Devender Rao     std::string type("client");
3908841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
3918841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
392b50789ceSJayanth Othayoth     std::string verifyUnit(unit);
393ddf64866SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
3948841dbd6SMarri Devender Rao     EXPECT_THROW(
3958841dbd6SMarri Devender Rao         {
3968841dbd6SMarri Devender Rao             try
3978841dbd6SMarri Devender Rao             {
3988841dbd6SMarri Devender Rao                 Certificate certificate(bus, objPath, type, unit, installPath,
3998f80c35bSMarri Devender Rao                                         certificateFile, false);
4008841dbd6SMarri Devender Rao             }
4018841dbd6SMarri Devender Rao             catch (const InvalidCertificate& e)
4028841dbd6SMarri Devender Rao             {
4038841dbd6SMarri Devender Rao                 throw;
4048841dbd6SMarri Devender Rao             }
4058841dbd6SMarri Devender Rao         },
4068841dbd6SMarri Devender Rao         InvalidCertificate);
4078841dbd6SMarri Devender Rao     EXPECT_FALSE(fs::exists(verifyPath));
4088841dbd6SMarri Devender Rao }
4098841dbd6SMarri Devender Rao 
4108841dbd6SMarri Devender Rao /** @brief Check install fails if ceritificate is missing in certificate file
4118841dbd6SMarri Devender Rao  */
4128841dbd6SMarri Devender Rao TEST_F(TestInvalidCertificate, TestMissingCeritificate)
4138841dbd6SMarri Devender Rao {
4148841dbd6SMarri Devender Rao     std::string endpoint("ldap");
4158841dbd6SMarri Devender Rao     std::string unit("");
4168841dbd6SMarri Devender Rao     std::string type("client");
4178841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + keyFile);
4188841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
4198841dbd6SMarri Devender Rao     std::string verifyUnit(unit);
4208841dbd6SMarri Devender Rao 
4218841dbd6SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
4228841dbd6SMarri Devender Rao     EXPECT_THROW(
4238841dbd6SMarri Devender Rao         {
4248841dbd6SMarri Devender Rao             try
4258841dbd6SMarri Devender Rao             {
4268841dbd6SMarri Devender Rao                 Certificate certificate(bus, objPath, type, unit, installPath,
4278f80c35bSMarri Devender Rao                                         keyFile, false);
4288841dbd6SMarri Devender Rao             }
4298841dbd6SMarri Devender Rao             catch (const InvalidCertificate& e)
4308841dbd6SMarri Devender Rao             {
4318841dbd6SMarri Devender Rao                 throw;
4328841dbd6SMarri Devender Rao             }
4338841dbd6SMarri Devender Rao         },
4348841dbd6SMarri Devender Rao         InvalidCertificate);
4358841dbd6SMarri Devender Rao     EXPECT_FALSE(fs::exists(verifyPath));
4368841dbd6SMarri Devender Rao }
4378841dbd6SMarri Devender Rao 
4388841dbd6SMarri Devender Rao /** @brief Check if Manager install method fails for invalid certificate file
4398841dbd6SMarri Devender Rao  */
4408841dbd6SMarri Devender Rao TEST_F(TestInvalidCertificate, TestCertManagerInstall)
4418841dbd6SMarri Devender Rao {
4428841dbd6SMarri Devender Rao     std::string endpoint("ldap");
4438841dbd6SMarri Devender Rao     std::string unit("");
4448841dbd6SMarri Devender Rao     std::string type("client");
4458841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
4468841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
4478841dbd6SMarri Devender Rao     std::string verifyUnit(unit);
4488841dbd6SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
449*f4682712SMarri Devender Rao     auto event = sdeventplus::Event::get_default();
450*f4682712SMarri Devender Rao     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
4518841dbd6SMarri Devender Rao                     std::move(installPath));
452ddf64866SMarri Devender Rao     MainApp mainApp(&manager);
453ddf64866SMarri Devender Rao     EXPECT_THROW(
454ddf64866SMarri Devender Rao         {
455ddf64866SMarri Devender Rao             try
456ddf64866SMarri Devender Rao             {
457ddf64866SMarri Devender Rao                 mainApp.install(certificateFile);
458ddf64866SMarri Devender Rao             }
459ddf64866SMarri Devender Rao             catch (const InvalidCertificate& e)
460ddf64866SMarri Devender Rao             {
461ddf64866SMarri Devender Rao                 throw;
462ddf64866SMarri Devender Rao             }
463ddf64866SMarri Devender Rao         },
464ddf64866SMarri Devender Rao         InvalidCertificate);
465ddf64866SMarri Devender Rao     EXPECT_FALSE(fs::exists(verifyPath));
466ddf64866SMarri Devender Rao }
467ddf64866SMarri Devender Rao 
4688841dbd6SMarri Devender Rao /** @brief Check if error is thrown when multiple certificates are installed
4698841dbd6SMarri Devender Rao  *  At present only one certificate per service is allowed
470ddf64866SMarri Devender Rao  */
4718841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestCertInstallNotAllowed)
472ddf64866SMarri Devender Rao {
4738841dbd6SMarri Devender Rao     using NotAllowed =
4748841dbd6SMarri Devender Rao         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
475ddf64866SMarri Devender Rao     std::string endpoint("ldap");
4768841dbd6SMarri Devender Rao     std::string unit("");
477ddf64866SMarri Devender Rao     std::string type("client");
4788841dbd6SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
4798841dbd6SMarri Devender Rao     std::string verifyPath(installPath);
480ddf64866SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
481*f4682712SMarri Devender Rao     auto event = sdeventplus::Event::get_default();
482*f4682712SMarri Devender Rao     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
4838841dbd6SMarri Devender Rao                     std::move(installPath));
484ddf64866SMarri Devender Rao     MainApp mainApp(&manager);
4858841dbd6SMarri Devender Rao     mainApp.install(certificateFile);
4868841dbd6SMarri Devender Rao     EXPECT_TRUE(fs::exists(verifyPath));
487ddf64866SMarri Devender Rao     EXPECT_THROW(
488ddf64866SMarri Devender Rao         {
489ddf64866SMarri Devender Rao             try
490ddf64866SMarri Devender Rao             {
4918841dbd6SMarri Devender Rao                 // install second certificate
4928841dbd6SMarri Devender Rao                 mainApp.install(certificateFile);
493ddf64866SMarri Devender Rao             }
4948841dbd6SMarri Devender Rao             catch (const NotAllowed& e)
495ddf64866SMarri Devender Rao             {
496ddf64866SMarri Devender Rao                 throw;
497ddf64866SMarri Devender Rao             }
498ddf64866SMarri Devender Rao         },
4998841dbd6SMarri Devender Rao         NotAllowed);
500e6597c5bSMarri Devender Rao }
501*f4682712SMarri Devender Rao 
502*f4682712SMarri Devender Rao TEST_F(TestCertificates, TestGenerateCSR)
503*f4682712SMarri Devender Rao {
504*f4682712SMarri Devender Rao     std::string endpoint("https");
505*f4682712SMarri Devender Rao     std::string unit("");
506*f4682712SMarri Devender Rao     std::string type("Server");
507*f4682712SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
508*f4682712SMarri Devender Rao     std::string verifyPath(installPath);
509*f4682712SMarri Devender Rao     std::string CSRPath(certDir + "/" + CSRFile);
510*f4682712SMarri Devender Rao     std::string privateKeyPath(certDir + "/" + privateKeyFile);
511*f4682712SMarri Devender Rao     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
512*f4682712SMarri Devender Rao     std::string challengePassword("0penBmc");
513*f4682712SMarri Devender Rao     std::string city("HYB");
514*f4682712SMarri Devender Rao     std::string commonName("abc.com");
515*f4682712SMarri Devender Rao     std::string contactPerson("Admin");
516*f4682712SMarri Devender Rao     std::string country("IN");
517*f4682712SMarri Devender Rao     std::string email("admin@in.ibm.com");
518*f4682712SMarri Devender Rao     std::string givenName("givenName");
519*f4682712SMarri Devender Rao     std::string initials("G");
520*f4682712SMarri Devender Rao     int64_t keyBitLength(2048);
521*f4682712SMarri Devender Rao     std::string keyCurveId("0");
522*f4682712SMarri Devender Rao     std::string keyPairAlgorithm("RSA");
523*f4682712SMarri Devender Rao     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
524*f4682712SMarri Devender Rao     std::string organization("IBM");
525*f4682712SMarri Devender Rao     std::string organizationalUnit("ISDL");
526*f4682712SMarri Devender Rao     std::string state("TS");
527*f4682712SMarri Devender Rao     std::string surname("surname");
528*f4682712SMarri Devender Rao     std::string unstructuredName("unstructuredName");
529*f4682712SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
530*f4682712SMarri Devender Rao     auto event = sdeventplus::Event::get_default();
531*f4682712SMarri Devender Rao     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
532*f4682712SMarri Devender Rao                     std::move(installPath));
533*f4682712SMarri Devender Rao     Status status;
534*f4682712SMarri Devender Rao     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
535*f4682712SMarri Devender Rao     MainApp mainApp(&manager, &csr);
536*f4682712SMarri Devender Rao     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
537*f4682712SMarri Devender Rao                         contactPerson, country, email, givenName, initials,
538*f4682712SMarri Devender Rao                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
539*f4682712SMarri Devender Rao                         organization, organizationalUnit, state, surname,
540*f4682712SMarri Devender Rao                         unstructuredName);
541*f4682712SMarri Devender Rao     std::string csrData("");
542*f4682712SMarri Devender Rao     // generateCSR takes considerable time to create CSR and privateKey Files
543*f4682712SMarri Devender Rao     EXPECT_FALSE(fs::exists(CSRPath));
544*f4682712SMarri Devender Rao     EXPECT_FALSE(fs::exists(privateKeyPath));
545*f4682712SMarri Devender Rao     EXPECT_THROW(
546*f4682712SMarri Devender Rao         {
547*f4682712SMarri Devender Rao             try
548*f4682712SMarri Devender Rao             {
549*f4682712SMarri Devender Rao                 csrData = csr.cSR();
550*f4682712SMarri Devender Rao             }
551*f4682712SMarri Devender Rao             catch (const InternalFailure& e)
552*f4682712SMarri Devender Rao             {
553*f4682712SMarri Devender Rao                 throw;
554*f4682712SMarri Devender Rao             }
555*f4682712SMarri Devender Rao         },
556*f4682712SMarri Devender Rao         InternalFailure);
557*f4682712SMarri Devender Rao     // wait for 10 sec to get CSR and privateKey Files generated
558*f4682712SMarri Devender Rao     sleep(10);
559*f4682712SMarri Devender Rao     EXPECT_TRUE(fs::exists(CSRPath));
560*f4682712SMarri Devender Rao     EXPECT_TRUE(fs::exists(privateKeyPath));
561*f4682712SMarri Devender Rao     csrData = csr.cSR();
562*f4682712SMarri Devender Rao     ASSERT_NE("", csrData.c_str());
563*f4682712SMarri Devender Rao }
564*f4682712SMarri Devender Rao 
565*f4682712SMarri Devender Rao TEST_F(TestCertificates, TestGenerateCSRError)
566*f4682712SMarri Devender Rao {
567*f4682712SMarri Devender Rao     std::string endpoint("https");
568*f4682712SMarri Devender Rao     std::string unit("");
569*f4682712SMarri Devender Rao     std::string type("Server");
570*f4682712SMarri Devender Rao     std::string installPath(certDir + "/" + certificateFile);
571*f4682712SMarri Devender Rao     std::string verifyPath(installPath);
572*f4682712SMarri Devender Rao     std::string CSRPath(certDir + "/" + CSRFile);
573*f4682712SMarri Devender Rao     std::string privateKeyPath(certDir + "/" + privateKeyFile);
574*f4682712SMarri Devender Rao     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
575*f4682712SMarri Devender Rao     std::string challengePassword("0penBmc");
576*f4682712SMarri Devender Rao     std::string city;
577*f4682712SMarri Devender Rao     std::string commonName;
578*f4682712SMarri Devender Rao     std::string contactPerson;
579*f4682712SMarri Devender Rao     std::string country;
580*f4682712SMarri Devender Rao     std::string email;
581*f4682712SMarri Devender Rao     std::string givenName;
582*f4682712SMarri Devender Rao     std::string initials;
583*f4682712SMarri Devender Rao     int64_t keyBitLength(12);
584*f4682712SMarri Devender Rao     std::string keyCurveId;
585*f4682712SMarri Devender Rao     std::string keyPairAlgorithm;
586*f4682712SMarri Devender Rao     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
587*f4682712SMarri Devender Rao     std::string organization;
588*f4682712SMarri Devender Rao     std::string organizationalUnit;
589*f4682712SMarri Devender Rao     std::string state;
590*f4682712SMarri Devender Rao     std::string surname;
591*f4682712SMarri Devender Rao     std::string unstructuredName;
592*f4682712SMarri Devender Rao     auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
593*f4682712SMarri Devender Rao     auto event = sdeventplus::Event::get_default();
594*f4682712SMarri Devender Rao     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
595*f4682712SMarri Devender Rao                     std::move(installPath));
596*f4682712SMarri Devender Rao     Status status;
597*f4682712SMarri Devender Rao     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
598*f4682712SMarri Devender Rao     MainApp mainApp(&manager, &csr);
599*f4682712SMarri Devender Rao     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
600*f4682712SMarri Devender Rao                         contactPerson, country, email, givenName, initials,
601*f4682712SMarri Devender Rao                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
602*f4682712SMarri Devender Rao                         organization, organizationalUnit, state, surname,
603*f4682712SMarri Devender Rao                         unstructuredName);
604*f4682712SMarri Devender Rao     sleep(10);
605*f4682712SMarri Devender Rao     EXPECT_FALSE(fs::exists(CSRPath));
606*f4682712SMarri Devender Rao     EXPECT_FALSE(fs::exists(privateKeyPath));
607*f4682712SMarri Devender Rao }
608