1 #pragma once
2 #include "utils.hpp"
3 
4 #include <openssl/evp.h>
5 #include <openssl/pem.h>
6 #include <openssl/rsa.h>
7 #include <sys/mman.h>
8 #include <unistd.h>
9 
10 #include <experimental/filesystem>
11 #include <set>
12 
13 namespace openpower
14 {
15 namespace software
16 {
17 namespace image
18 {
19 
20 namespace fs = std::experimental::filesystem;
21 using Key_t = std::string;
22 using Hash_t = std::string;
23 using PublicKeyPath = fs::path;
24 using HashFilePath = fs::path;
25 using KeyHashPathPair = std::pair<HashFilePath, PublicKeyPath>;
26 using AvailableKeyTypes = std::set<Key_t>;
27 
28 // RAII support for openSSL functions.
29 using BIO_MEM_Ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
30 using EVP_PKEY_Ptr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
31 using EVP_MD_CTX_Ptr =
32     std::unique_ptr<EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)>;
33 
34 // PNOR flash image file name.
35 constexpr auto squashFSImage = "pnor.xz.squashfs";
36 
37 /** @struct CustomFd
38  *
39  *  RAII wrapper for file descriptor.
40  */
41 struct CustomFd
42 {
43   public:
44     CustomFd() = delete;
45     CustomFd(const CustomFd&) = delete;
46     CustomFd& operator=(const CustomFd&) = delete;
47     CustomFd(CustomFd&&) = default;
48     CustomFd& operator=(CustomFd&&) = default;
49     /** @brief Saves File descriptor and uses it to do file operation
50      *
51      *  @param[in] fd - File descriptor
52      */
53     CustomFd(int fd) : fd(fd)
54     {
55     }
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     }
103 
104     ~CustomMap()
105     {
106         munmap(addr, length);
107     }
108 
109     void* operator()() const
110     {
111         return addr;
112     }
113 };
114 
115 /** @class Signature
116  *  @brief Contains signature verification functions.
117  *  @details The software image class that contains the signature
118  *           verification functions for signed image.
119  */
120 class Signature
121 {
122   public:
123     Signature() = delete;
124     Signature(const Signature&) = delete;
125     Signature& operator=(const Signature&) = delete;
126     Signature(Signature&&) = default;
127     Signature& operator=(Signature&&) = default;
128     ~Signature() = default;
129 
130     /**
131      * @brief Constructs Signature.
132      * @param[in]  imageDirPath - image path
133      * @param[in]  signedConfPath - Path of public key
134      *                              hash function files
135      */
136     Signature(const fs::path& imageDirPath, const fs::path& signedConfPath);
137 
138     /**
139      * @brief Image signature verification function.
140      *        Verify the Manifest and public key file signature using the
141      *        public keys available in the system first. After successful
142      *        validation, continue the whole image files signature
143      *        validation using the image specific public key and the
144      *        hash function.
145      *
146      *        @return true if signature verification was successful,
147      *                     false if not
148      */
149     bool verify();
150 
151   private:
152     /**
153      * @brief Function used for system level file signature validation
154      *        of image specific publickey file and manifest file
155      *        using the available public keys and hash functions
156      *        in the system.
157      *        Refer code-update documentation for more details.
158      */
159     bool systemLevelVerify();
160 
161     /**
162      *  @brief Return all key types stored in the BMC based on the
163      *         public key and hashfunc files stored in the BMC.
164      *
165      *  @return list
166      */
167     AvailableKeyTypes getAvailableKeyTypesFromSystem() const;
168 
169     /**
170      *  @brief Return public key and hash function file names for the
171      *  corresponding key type
172      *
173      *  @param[in]  key - key type
174      *  @return Pair of hash and public key file names
175      */
176     inline KeyHashPathPair getKeyHashFileNames(const Key_t& key) const;
177 
178     /**
179      * @brief Verify the file signature using public key and hash function
180      *
181      * @param[in]  - Image file path
182      * @param[in]  - Signature file path
183      * @param[in]  - Public key
184      * @param[in]  - Hash function name
185      * @return true if signature verification was successful, false if not
186      */
187     bool verifyFile(const fs::path& file, const fs::path& signature,
188                     const fs::path& publicKey, const std::string& hashFunc);
189 
190     /**
191      * @brief Create RSA object from the public key
192      * @param[in]  - publickey
193      * @param[out] - RSA Object.
194      */
195     inline RSA* createPublicRSA(const fs::path& publicKey);
196 
197     /**
198      * @brief Memory map the  file
199      * @param[in]  - file path
200      * @param[in]  - file size
201      * @param[out] - Custom Mmap address
202      */
203     CustomMap mapFile(const fs::path& path, size_t size);
204 
205     /** @brief Directory where software images are placed*/
206     fs::path imageDirPath;
207 
208     /** @brief Path of public key and hash function files */
209     fs::path signedConfPath;
210 
211     /** @brief key type defined in mainfest file */
212     Key_t keyType;
213 
214     /** @brief Hash type defined in mainfest file */
215     Hash_t hashType;
216 };
217 
218 } // namespace image
219 } // namespace software
220 } // namespace openpower
221