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