xref: /openbmc/phosphor-bmc-code-mgmt/bmc/image_verify.hpp (revision 994a77ff25aeb28b2cce7142d081af767f9eb542)
1 #pragma once
2 #include "openssl_alloc.hpp"
3 #include "version.hpp"
4 
5 #include <openssl/evp.h>
6 #include <openssl/pem.h>
7 #include <openssl/rsa.h>
8 #include <sys/mman.h>
9 #include <unistd.h>
10 
11 #include <filesystem>
12 #include <set>
13 #include <string>
14 #include <vector>
15 
16 namespace phosphor
17 {
18 namespace software
19 {
20 namespace image
21 {
22 
23 namespace fs = std::filesystem;
24 using Key_t = std::string;
25 using Hash_t = std::string;
26 using PublicKeyPath = fs::path;
27 using HashFilePath = fs::path;
28 using KeyHashPathPair = std::pair<HashFilePath, PublicKeyPath>;
29 using AvailableKeyTypes = std::set<Key_t>;
30 using VersionPurpose =
31     sdbusplus::server::xyz::openbmc_project::software::Version::VersionPurpose;
32 
33 // RAII support for openSSL functions.
34 using BIO_MEM_Ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
35 using EVP_PKEY_Ptr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
36 using EVP_MD_CTX_Ptr =
37     std::unique_ptr<EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)>;
38 
39 /** @struct CustomFd
40  *
41  *  RAII wrapper for file descriptor.
42  */
43 struct CustomFd
44 {
45   public:
46     CustomFd() = delete;
47     CustomFd(const CustomFd&) = delete;
48     CustomFd& operator=(const CustomFd&) = delete;
49     CustomFd(CustomFd&&) = default;
50     CustomFd& operator=(CustomFd&&) = default;
51     /** @brief Saves File descriptor and uses it to do file operation
52      *
53      *  @param[in] fd - File descriptor
54      */
55     explicit CustomFd(int fd) : fd(fd) {}
56 
57     ~CustomFd()
58     {
59         if (fd >= 0)
60         {
61             close(fd);
62         }
63     }
64 
65     int operator()() const
66     {
67         return fd;
68     }
69 
70   private:
71     /** @brief File descriptor */
72     int fd = -1;
73 };
74 
75 /** @struct CustomMap
76  *
77  *  RAII wrapper for mmap.
78  */
79 struct CustomMap
80 {
81   private:
82     /** @brief starting address of the map   */
83     void* addr;
84 
85     /** @brief length of the mapping   */
86     size_t length;
87 
88   public:
89     CustomMap() = delete;
90     CustomMap(const CustomMap&) = delete;
91     CustomMap& operator=(const CustomMap&) = delete;
92     CustomMap(CustomMap&&) = default;
93     CustomMap& operator=(CustomMap&&) = default;
94 
95     /** @brief Saves starting address of the map and
96      *         and length of the file.
97      *  @param[in]  addr - Starting address of the map
98      *  @param[in]  length - length of the map
99      */
100     CustomMap(void* addr, size_t length) : addr(addr), length(length) {}
101 
102     ~CustomMap()
103     {
104         munmap(addr, length);
105     }
106 
107     void* operator()() const
108     {
109         return addr;
110     }
111 };
112 
113 /** @class Signature
114  *  @brief Contains signature verification functions.
115  *  @details The software image class that contains the signature
116  *           verification functions for signed image.
117  */
118 class Signature
119 {
120   public:
121     Signature() = delete;
122     Signature(const Signature&) = delete;
123     Signature& operator=(const Signature&) = delete;
124     Signature(Signature&&) = default;
125     Signature& operator=(Signature&&) = default;
126     ~Signature() = default;
127 
128     /**
129      * @brief Constructs Signature.
130      * @param[in]  imageDirPath - image path
131      * @param[in]  signedConfPath - Path of public key
132      *                              hash function files
133      */
134     Signature(const fs::path& imageDirPath, const fs::path& signedConfPath);
135 
136     /**
137      * @brief Image signature verification function.
138      *        Verify the Manifest and public key file signature using the
139      *        public keys available in the system first. After successful
140      *        validation, continue the whole image files signature
141      *        validation using the image specific public key and the
142      *        hash function.
143      *
144      *        @return true if signature verification was successful,
145      *                     false if not
146      */
147     bool verify();
148 
149   private:
150     /**
151      * @brief Function used for system level file signature validation
152      *        of image specific publickey file and manifest file
153      *        using the available public keys and hash functions
154      *        in the system.
155      *        Refer code-update documentation for more details.
156      */
157     bool systemLevelVerify();
158 
159     /**
160      *  @brief Return all key types stored in the BMC based on the
161      *         public key and hashfunc files stored in the BMC.
162      *
163      *  @return list
164      */
165     AvailableKeyTypes getAvailableKeyTypesFromSystem() const;
166 
167     /**
168      *  @brief Return public key and hash function file names for the
169      *  corresponding key type
170      *
171      *  @param[in]  key - key type
172      *  @return Pair of hash and public key file names
173      */
174     inline KeyHashPathPair getKeyHashFileNames(const Key_t& key) const;
175 
176     /**
177      * @brief Verify the file signature using public key and hash function
178      *
179      * @param[in]  - Image file path
180      * @param[in]  - Signature file path
181      * @param[in]  - Public key
182      * @param[in]  - Hash function name
183      * @return true if signature verification was successful, false if not
184      */
185     static bool verifyFile(const fs::path& file, const fs::path& signature,
186                            const fs::path& publicKey,
187                            const std::string& hashFunc);
188 
189     /**
190      * @brief Create RSA object from the public key
191      * @param[in]  - publickey
192      * @param[out] - RSA Object.
193      */
194     static inline EVP_PKEY_Ptr createPublicRSA(const fs::path& publicKey);
195 
196     /**
197      * @brief Memory map the  file
198      * @param[in]  - file path
199      * @param[in]  - file size
200      * @param[out] - Custom Mmap address
201      */
202     static CustomMap mapFile(const fs::path& path, size_t size);
203 
204     /**
205      * @brief Verify the full file signature using public key and hash function
206      *
207      * @return true if signature verification was successful, false if not
208      */
209     bool verifyFullImage();
210 
211     /** @brief Directory where software images are placed*/
212     fs::path imageDirPath;
213 
214     /** @brief Path of public key and hash function files */
215     fs::path signedConfPath;
216 
217     /** @brief key type defined in manifest file */
218     Key_t keyType;
219 
220     /** @brief Hash type defined in manifest file */
221     Hash_t hashType;
222 
223     /** @brief The image purpose */
224     VersionPurpose purpose;
225 
226     /** @brief Check and Verify the required image files
227      *
228      * @param[in] filePath - BMC tarball file path
229      * @param[in] publicKeyPath - publicKey file Path
230      * @param[in] imageList - Image filenames included in the BMC tarball
231      * @param[out] fileFound - Indicate if the file to verify is found or not
232      *
233      * @return true if all image files are found in BMC tarball and
234      * Verify Success false if one of image files is missing
235      */
236     bool checkAndVerifyImage(const std::string& filePath,
237                              const std::string& publicKeyPath,
238                              const std::vector<std::string>& imageList,
239                              bool& fileFound);
240 };
241 
242 } // namespace image
243 } // namespace software
244 } // namespace phosphor
245