19d7cd834SJayanth Othayoth #pragma once
2a013560fSJayashankar Padath #include "openssl_alloc.hpp"
36173a079SLei YU #include "version.hpp"
4b0ce996aSGunnar Mills 
5fb6e1fc2SJayanth Othayoth #include <openssl/evp.h>
6fb6e1fc2SJayanth Othayoth #include <openssl/pem.h>
7b0ce996aSGunnar Mills #include <openssl/rsa.h>
8b0ce996aSGunnar Mills #include <sys/mman.h>
9b0ce996aSGunnar Mills #include <unistd.h>
10b0ce996aSGunnar Mills 
11c98d912eSAdriana Kobylak #include <filesystem>
122ab9b109SJayanth Othayoth #include <set>
139155b713SAndrew Geissler #include <string>
14574f94bcSHenry Tian #include <vector>
159d7cd834SJayanth Othayoth 
169d7cd834SJayanth Othayoth namespace phosphor
179d7cd834SJayanth Othayoth {
189d7cd834SJayanth Othayoth namespace software
199d7cd834SJayanth Othayoth {
209d7cd834SJayanth Othayoth namespace image
219d7cd834SJayanth Othayoth {
229d7cd834SJayanth Othayoth 
23c98d912eSAdriana Kobylak namespace fs = std::filesystem;
242ab9b109SJayanth Othayoth using Key_t = std::string;
252ab9b109SJayanth Othayoth using Hash_t = std::string;
262ab9b109SJayanth Othayoth using PublicKeyPath = fs::path;
272ab9b109SJayanth Othayoth using HashFilePath = fs::path;
282ab9b109SJayanth Othayoth using KeyHashPathPair = std::pair<HashFilePath, PublicKeyPath>;
292ab9b109SJayanth Othayoth using AvailableKeyTypes = std::set<Key_t>;
306173a079SLei YU using VersionPurpose =
311e9a5f1aSPatrick Williams     sdbusplus::server::xyz::openbmc_project::software::Version::VersionPurpose;
329d7cd834SJayanth Othayoth 
33fb6e1fc2SJayanth Othayoth // RAII support for openSSL functions.
34fb6e1fc2SJayanth Othayoth using BIO_MEM_Ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
35fb6e1fc2SJayanth Othayoth using EVP_PKEY_Ptr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
36fb6e1fc2SJayanth Othayoth using EVP_MD_CTX_Ptr =
375ed9b2d7SAdriana Kobylak     std::unique_ptr<EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)>;
38fb6e1fc2SJayanth Othayoth 
39fb6e1fc2SJayanth Othayoth /** @struct CustomFd
40fb6e1fc2SJayanth Othayoth  *
41fb6e1fc2SJayanth Othayoth  *  RAII wrapper for file descriptor.
42fb6e1fc2SJayanth Othayoth  */
43fb6e1fc2SJayanth Othayoth struct CustomFd
44fb6e1fc2SJayanth Othayoth {
45fb6e1fc2SJayanth Othayoth   public:
46fb6e1fc2SJayanth Othayoth     CustomFd() = delete;
47fb6e1fc2SJayanth Othayoth     CustomFd(const CustomFd&) = delete;
48fb6e1fc2SJayanth Othayoth     CustomFd& operator=(const CustomFd&) = delete;
49fb6e1fc2SJayanth Othayoth     CustomFd(CustomFd&&) = default;
50fb6e1fc2SJayanth Othayoth     CustomFd& operator=(CustomFd&&) = default;
51fb6e1fc2SJayanth Othayoth     /** @brief Saves File descriptor and uses it to do file operation
52fb6e1fc2SJayanth Othayoth      *
53fb6e1fc2SJayanth Othayoth      *  @param[in] fd - File descriptor
54fb6e1fc2SJayanth Othayoth      */
CustomFdphosphor::software::image::CustomFd55d5e8e73bSPatrick Williams     explicit CustomFd(int fd) : fd(fd) {}
56fb6e1fc2SJayanth Othayoth 
~CustomFdphosphor::software::image::CustomFd57fb6e1fc2SJayanth Othayoth     ~CustomFd()
58fb6e1fc2SJayanth Othayoth     {
59fb6e1fc2SJayanth Othayoth         if (fd >= 0)
60fb6e1fc2SJayanth Othayoth         {
61fb6e1fc2SJayanth Othayoth             close(fd);
62fb6e1fc2SJayanth Othayoth         }
63fb6e1fc2SJayanth Othayoth     }
64fb6e1fc2SJayanth Othayoth 
operator ()phosphor::software::image::CustomFd65fb6e1fc2SJayanth Othayoth     int operator()() const
66fb6e1fc2SJayanth Othayoth     {
67fb6e1fc2SJayanth Othayoth         return fd;
68fb6e1fc2SJayanth Othayoth     }
69fb6e1fc2SJayanth Othayoth 
70fb6e1fc2SJayanth Othayoth   private:
71fb6e1fc2SJayanth Othayoth     /** @brief File descriptor */
72fb6e1fc2SJayanth Othayoth     int fd = -1;
73fb6e1fc2SJayanth Othayoth };
74fb6e1fc2SJayanth Othayoth 
75fb6e1fc2SJayanth Othayoth /** @struct CustomMap
76fb6e1fc2SJayanth Othayoth  *
77fb6e1fc2SJayanth Othayoth  *  RAII wrapper for mmap.
78fb6e1fc2SJayanth Othayoth  */
79fb6e1fc2SJayanth Othayoth struct CustomMap
80fb6e1fc2SJayanth Othayoth {
81fb6e1fc2SJayanth Othayoth   private:
82fb6e1fc2SJayanth Othayoth     /** @brief starting address of the map   */
83fb6e1fc2SJayanth Othayoth     void* addr;
84fb6e1fc2SJayanth Othayoth 
85fb6e1fc2SJayanth Othayoth     /** @brief length of the mapping   */
86fb6e1fc2SJayanth Othayoth     size_t length;
87fb6e1fc2SJayanth Othayoth 
88fb6e1fc2SJayanth Othayoth   public:
89fb6e1fc2SJayanth Othayoth     CustomMap() = delete;
90fb6e1fc2SJayanth Othayoth     CustomMap(const CustomMap&) = delete;
91fb6e1fc2SJayanth Othayoth     CustomMap& operator=(const CustomMap&) = delete;
92fb6e1fc2SJayanth Othayoth     CustomMap(CustomMap&&) = default;
93fb6e1fc2SJayanth Othayoth     CustomMap& operator=(CustomMap&&) = default;
94fb6e1fc2SJayanth Othayoth 
95fb6e1fc2SJayanth Othayoth     /** @brief Saves starting address of the map and
96fb6e1fc2SJayanth Othayoth      *         and length of the file.
97fb6e1fc2SJayanth Othayoth      *  @param[in]  addr - Starting address of the map
98fb6e1fc2SJayanth Othayoth      *  @param[in]  length - length of the map
99fb6e1fc2SJayanth Othayoth      */
CustomMapphosphor::software::image::CustomMap100d5e8e73bSPatrick Williams     CustomMap(void* addr, size_t length) : addr(addr), length(length) {}
101fb6e1fc2SJayanth Othayoth 
~CustomMapphosphor::software::image::CustomMap102fb6e1fc2SJayanth Othayoth     ~CustomMap()
103fb6e1fc2SJayanth Othayoth     {
104fb6e1fc2SJayanth Othayoth         munmap(addr, length);
105fb6e1fc2SJayanth Othayoth     }
106fb6e1fc2SJayanth Othayoth 
operator ()phosphor::software::image::CustomMap107fb6e1fc2SJayanth Othayoth     void* operator()() const
108fb6e1fc2SJayanth Othayoth     {
109fb6e1fc2SJayanth Othayoth         return addr;
110fb6e1fc2SJayanth Othayoth     }
111fb6e1fc2SJayanth Othayoth };
112fb6e1fc2SJayanth Othayoth 
1139d7cd834SJayanth Othayoth /** @class Signature
1149d7cd834SJayanth Othayoth  *  @brief Contains signature verification functions.
1159d7cd834SJayanth Othayoth  *  @details The software image class that contains the signature
1169d7cd834SJayanth Othayoth  *           verification functions for signed image.
1179d7cd834SJayanth Othayoth  */
1189d7cd834SJayanth Othayoth class Signature
1199d7cd834SJayanth Othayoth {
1209d7cd834SJayanth Othayoth   public:
1219d7cd834SJayanth Othayoth     Signature() = delete;
1229d7cd834SJayanth Othayoth     Signature(const Signature&) = delete;
1239d7cd834SJayanth Othayoth     Signature& operator=(const Signature&) = delete;
1249d7cd834SJayanth Othayoth     Signature(Signature&&) = default;
1259d7cd834SJayanth Othayoth     Signature& operator=(Signature&&) = default;
1269d7cd834SJayanth Othayoth     ~Signature() = default;
1279d7cd834SJayanth Othayoth 
1282ab9b109SJayanth Othayoth     /**
1292ab9b109SJayanth Othayoth      * @brief Constructs Signature.
1302ab9b109SJayanth Othayoth      * @param[in]  imageDirPath - image path
1312ab9b109SJayanth Othayoth      * @param[in]  signedConfPath - Path of public key
1322ab9b109SJayanth Othayoth      *                              hash function files
1339d7cd834SJayanth Othayoth      */
1342ab9b109SJayanth Othayoth     Signature(const fs::path& imageDirPath, const fs::path& signedConfPath);
1359d7cd834SJayanth Othayoth 
1369d7cd834SJayanth Othayoth     /**
1379d7cd834SJayanth Othayoth      * @brief Image signature verification function.
1389d7cd834SJayanth Othayoth      *        Verify the Manifest and public key file signature using the
1399d7cd834SJayanth Othayoth      *        public keys available in the system first. After successful
1409d7cd834SJayanth Othayoth      *        validation, continue the whole image files signature
1419d7cd834SJayanth Othayoth      *        validation using the image specific public key and the
1429d7cd834SJayanth Othayoth      *        hash function.
1439d7cd834SJayanth Othayoth      *
1449d7cd834SJayanth Othayoth      *        @return true if signature verification was successful,
1459d7cd834SJayanth Othayoth      *                     false if not
1469d7cd834SJayanth Othayoth      */
1479d7cd834SJayanth Othayoth     bool verify();
1489d7cd834SJayanth Othayoth 
1499d7cd834SJayanth Othayoth   private:
1502ab9b109SJayanth Othayoth     /**
1512ab9b109SJayanth Othayoth      * @brief Function used for system level file signature validation
152e11a2028SGunnar Mills      *        of image specific publickey file and manifest file
1532ab9b109SJayanth Othayoth      *        using the available public keys and hash functions
1542ab9b109SJayanth Othayoth      *        in the system.
1552bcba02aSGunnar Mills      *        Refer code-update documentation for more details.
1562ab9b109SJayanth Othayoth      */
1572ab9b109SJayanth Othayoth     bool systemLevelVerify();
1582ab9b109SJayanth Othayoth 
1592ab9b109SJayanth Othayoth     /**
1602ab9b109SJayanth Othayoth      *  @brief Return all key types stored in the BMC based on the
1612ab9b109SJayanth Othayoth      *         public key and hashfunc files stored in the BMC.
1622ab9b109SJayanth Othayoth      *
1632ab9b109SJayanth Othayoth      *  @return list
1642ab9b109SJayanth Othayoth      */
1652ab9b109SJayanth Othayoth     AvailableKeyTypes getAvailableKeyTypesFromSystem() const;
1662ab9b109SJayanth Othayoth 
1672ab9b109SJayanth Othayoth     /**
1682ab9b109SJayanth Othayoth      *  @brief Return public key and hash function file names for the
1692ab9b109SJayanth Othayoth      *  corresponding key type
1702ab9b109SJayanth Othayoth      *
1712ab9b109SJayanth Othayoth      *  @param[in]  key - key type
1722ab9b109SJayanth Othayoth      *  @return Pair of hash and public key file names
1732ab9b109SJayanth Othayoth      */
1742ab9b109SJayanth Othayoth     inline KeyHashPathPair getKeyHashFileNames(const Key_t& key) const;
1752ab9b109SJayanth Othayoth 
1762ab9b109SJayanth Othayoth     /**
1772ab9b109SJayanth Othayoth      * @brief Verify the file signature using public key and hash function
1782ab9b109SJayanth Othayoth      *
1792ab9b109SJayanth Othayoth      * @param[in]  - Image file path
1802ab9b109SJayanth Othayoth      * @param[in]  - Signature file path
1812ab9b109SJayanth Othayoth      * @param[in]  - Public key
1822ab9b109SJayanth Othayoth      * @param[in]  - Hash function name
1832ab9b109SJayanth Othayoth      * @return true if signature verification was successful, false if not
1842ab9b109SJayanth Othayoth      */
1852ab9b109SJayanth Othayoth     bool verifyFile(const fs::path& file, const fs::path& signature,
1862ab9b109SJayanth Othayoth                     const fs::path& publicKey, const std::string& hashFunc);
1872ab9b109SJayanth Othayoth 
188fb6e1fc2SJayanth Othayoth     /**
189fb6e1fc2SJayanth Othayoth      * @brief Create RSA object from the public key
190fb6e1fc2SJayanth Othayoth      * @param[in]  - publickey
191fb6e1fc2SJayanth Othayoth      * @param[out] - RSA Object.
192fb6e1fc2SJayanth Othayoth      */
193d75c869dSPatrick Williams     inline EVP_PKEY_Ptr createPublicRSA(const fs::path& publicKey);
194fb6e1fc2SJayanth Othayoth 
195fb6e1fc2SJayanth Othayoth     /**
196fb6e1fc2SJayanth Othayoth      * @brief Memory map the  file
197fb6e1fc2SJayanth Othayoth      * @param[in]  - file path
198fb6e1fc2SJayanth Othayoth      * @param[in]  - file size
199fb6e1fc2SJayanth Othayoth      * @param[out] - Custom Mmap address
200fb6e1fc2SJayanth Othayoth      */
201fb6e1fc2SJayanth Othayoth     CustomMap mapFile(const fs::path& path, size_t size);
202fb6e1fc2SJayanth Othayoth 
2030a06e97fSGeorge Liu     /**
2040a06e97fSGeorge Liu      * @brief Verify the full file signature using public key and hash function
2050a06e97fSGeorge Liu      *
2060a06e97fSGeorge Liu      * @return true if signature verification was successful, false if not
2070a06e97fSGeorge Liu      */
2080a06e97fSGeorge Liu     bool verifyFullImage();
2090a06e97fSGeorge Liu 
2109d7cd834SJayanth Othayoth     /** @brief Directory where software images are placed*/
2119d7cd834SJayanth Othayoth     fs::path imageDirPath;
2122ab9b109SJayanth Othayoth 
2132ab9b109SJayanth Othayoth     /** @brief Path of public key and hash function files */
2142ab9b109SJayanth Othayoth     fs::path signedConfPath;
2152ab9b109SJayanth Othayoth 
216*19dd56beSManojkiran Eda     /** @brief key type defined in manifest file */
2172ab9b109SJayanth Othayoth     Key_t keyType;
2182ab9b109SJayanth Othayoth 
219*19dd56beSManojkiran Eda     /** @brief Hash type defined in manifest file */
2202ab9b109SJayanth Othayoth     Hash_t hashType;
221574f94bcSHenry Tian 
2226173a079SLei YU     /** @brief The image purpose */
2236173a079SLei YU     VersionPurpose purpose;
2246173a079SLei YU 
225574f94bcSHenry Tian     /** @brief Check and Verify the required image files
226574f94bcSHenry Tian      *
227574f94bcSHenry Tian      * @param[in] filePath - BMC tarball file path
228574f94bcSHenry Tian      * @param[in] publicKeyPath - publicKey file Path
229574f94bcSHenry Tian      * @param[in] imageList - Image filenames included in the BMC tarball
2307ab55e20SLei YU      * @param[out] fileFound - Indicate if the file to verify is found or not
2317ab55e20SLei YU      *
2327ab55e20SLei YU      * @return true if all image files are found in BMC tarball and
233*19dd56beSManojkiran Eda      * Verify Success false if one of image files is missing
234574f94bcSHenry Tian      */
235574f94bcSHenry Tian     bool checkAndVerifyImage(const std::string& filePath,
236574f94bcSHenry Tian                              const std::string& publicKeyPath,
2377ab55e20SLei YU                              const std::vector<std::string>& imageList,
2387ab55e20SLei YU                              bool& fileFound);
2399d7cd834SJayanth Othayoth };
2409d7cd834SJayanth Othayoth 
2419d7cd834SJayanth Othayoth } // namespace image
2429d7cd834SJayanth Othayoth } // namespace software
2439d7cd834SJayanth Othayoth } // namespace phosphor
244