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