18c0446c1STom Joseph #pragma once 28c0446c1STom Joseph 3ba11f792STom Joseph #include "crypt_algo.hpp" 4dd1be1a2STom Joseph #include "integrity_algo.hpp" 58c0446c1STom Joseph 69e801a2bSVernon Mauery #include <array> 79d9b7638SAndrew Geissler #include <cstddef> 87408e76aSAndrew Geissler #include <string> 99e801a2bSVernon Mauery #include <vector> 109e801a2bSVernon Mauery 118c0446c1STom Joseph namespace cipher 128c0446c1STom Joseph { 138c0446c1STom Joseph namespace rakp_auth 148c0446c1STom Joseph { 158c0446c1STom Joseph constexpr size_t USER_KEY_MAX_LENGTH = 20; 168c0446c1STom Joseph constexpr size_t BMC_RANDOM_NUMBER_LEN = 16; 178c0446c1STom Joseph constexpr size_t REMOTE_CONSOLE_RANDOM_NUMBER_LEN = 16; 188c0446c1STom Joseph 193563f8feSTom Joseph /** 208c0446c1STom Joseph * @enum RAKP Authentication Algorithms 218c0446c1STom Joseph * 228c0446c1STom Joseph * RMCP+ Authenticated Key-Exchange Protocol (RAKP) 238c0446c1STom Joseph * 248c0446c1STom Joseph * RAKP-None is not supported as per the following recommendation 258c0446c1STom Joseph * (https://www.us-cert.gov/ncas/alerts/TA13-207A) 268c0446c1STom Joseph * ("cipher 0" is an option enabled by default on many IPMI enabled devices that 278c0446c1STom Joseph * allows authentication to be bypassed. Disable "cipher 0" to prevent 288c0446c1STom Joseph * attackers from bypassing authentication and sending arbitrary IPMI commands.) 298c0446c1STom Joseph */ 308c0446c1STom Joseph enum class Algorithms : uint8_t 318c0446c1STom Joseph { 32fe5a6458STom Joseph RAKP_NONE = 0, // Mandatory (implemented, not supported) 33fe5a6458STom Joseph RAKP_HMAC_SHA1, // Mandatory (implemented, default choice in ipmitool) 34fe5a6458STom Joseph RAKP_HMAC_MD5, // Optional (not implemented) 35fe5a6458STom Joseph RAKP_HMAC_SHA256, // Optional (implemented, best available) 368c0446c1STom Joseph // Reserved used to indicate an invalid authentication algorithm 378c0446c1STom Joseph RAKP_HMAC_INVALID = 0xB0 388c0446c1STom Joseph }; 398c0446c1STom Joseph 403563f8feSTom Joseph /** 418c0446c1STom Joseph * @class Interface 428c0446c1STom Joseph * 438c0446c1STom Joseph * Interface is the base class for the Authentication Algorithms. 448c0446c1STom Joseph * The Authentication Algorithm specifies the type of authentication “handshake” 458c0446c1STom Joseph * process that is used and identifies any particular variations of hashing or 468c0446c1STom Joseph * signature algorithm that is used as part of the process. 478c0446c1STom Joseph * 488c0446c1STom Joseph */ 498c0446c1STom Joseph class Interface 508c0446c1STom Joseph { 518c0446c1STom Joseph public: Interface(integrity::Algorithms intAlgo,crypt::Algorithms cryptAlgo)52ba11f792STom Joseph explicit Interface(integrity::Algorithms intAlgo, 53ba11f792STom Joseph crypt::Algorithms cryptAlgo) : 548425624aSPatrick Williams intAlgo(intAlgo), cryptAlgo(cryptAlgo) 55bc8958feSGeorge Liu {} 56ba11f792STom Joseph 57dd1be1a2STom Joseph Interface() = delete; 588c0446c1STom Joseph virtual ~Interface() = default; 598c0446c1STom Joseph Interface(const Interface&) = default; 608c0446c1STom Joseph Interface& operator=(const Interface&) = default; 618c0446c1STom Joseph Interface(Interface&&) = default; 628c0446c1STom Joseph Interface& operator=(Interface&&) = default; 638c0446c1STom Joseph 643563f8feSTom Joseph /** 658c0446c1STom Joseph * @brief Generate the Hash Message Authentication Code 668c0446c1STom Joseph * 678c0446c1STom Joseph * This API is invoked to generate the Key Exchange Authentication Code 688c0446c1STom Joseph * in the RAKP2 and RAKP4 sequence and for generating the Session 698c0446c1STom Joseph * Integrity Key. 708c0446c1STom Joseph * 718c0446c1STom Joseph * @param input message 728c0446c1STom Joseph * 738c0446c1STom Joseph * @return hash output 748c0446c1STom Joseph * 758c0446c1STom Joseph * @note The user key which is the secret key for the hash operation 768c0446c1STom Joseph * needs to be set before this operation. 778c0446c1STom Joseph */ 788c0446c1STom Joseph std::vector<uint8_t> virtual generateHMAC( 7970fd29cfSVernon Mauery const std::vector<uint8_t>& input) const = 0; 808c0446c1STom Joseph 813563f8feSTom Joseph /** 828c0446c1STom Joseph * @brief Generate the Integrity Check Value 838c0446c1STom Joseph * 848c0446c1STom Joseph * This API is invoked in the RAKP4 sequence for generating the 858c0446c1STom Joseph * Integrity Check Value. 868c0446c1STom Joseph * 878c0446c1STom Joseph * @param input message 888c0446c1STom Joseph * 898c0446c1STom Joseph * @return hash output 908c0446c1STom Joseph * 918c0446c1STom Joseph * @note The session integrity key which is the secret key for the 928c0446c1STom Joseph * hash operation needs to be set before this operation. 938c0446c1STom Joseph */ 948c0446c1STom Joseph std::vector<uint8_t> virtual generateICV( 9570fd29cfSVernon Mauery const std::vector<uint8_t>& input) const = 0; 968c0446c1STom Joseph 979b307be6SVernon Mauery /** 989b307be6SVernon Mauery * @brief Check if the Authentication algorithm is supported 999b307be6SVernon Mauery * 1009b307be6SVernon Mauery * @param[in] algo - authentication algorithm 1019b307be6SVernon Mauery * 1029b307be6SVernon Mauery * @return true if algorithm is supported else false 1039b307be6SVernon Mauery * 1049b307be6SVernon Mauery */ isAlgorithmSupported(Algorithms algo)1059b307be6SVernon Mauery static bool isAlgorithmSupported(Algorithms algo) 1069b307be6SVernon Mauery { 1074c494398SSuryakanth Sekar if (algo == Algorithms::RAKP_HMAC_SHA256) 1089b307be6SVernon Mauery { 1099b307be6SVernon Mauery return true; 1109b307be6SVernon Mauery } 1119b307be6SVernon Mauery else 1129b307be6SVernon Mauery { 1139b307be6SVernon Mauery return false; 1149b307be6SVernon Mauery } 1159b307be6SVernon Mauery } 1169b307be6SVernon Mauery 1178c0446c1STom Joseph // User Key is hardcoded to PASSW0RD till the IPMI User account 1188c0446c1STom Joseph // management is in place. 119e2e97660STom Joseph std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"0penBmc"}; 1208c0446c1STom Joseph 1218c0446c1STom Joseph // Managed System Random Number 1228c0446c1STom Joseph std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum; 1238c0446c1STom Joseph 1248c0446c1STom Joseph // Remote Console Random Number 1258c0446c1STom Joseph std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum; 1268c0446c1STom Joseph 1278c0446c1STom Joseph // Session Integrity Key 1288c0446c1STom Joseph std::vector<uint8_t> sessionIntegrityKey; 129dd1be1a2STom Joseph 1303563f8feSTom Joseph /** 131dd1be1a2STom Joseph * Integrity Algorithm is activated and set in the session data only 132dd1be1a2STom Joseph * once the session setup is succeeded in the RAKP34 command. But the 133dd1be1a2STom Joseph * integrity algorithm is negotiated in the Open Session Request command 134ba11f792STom Joseph * . So the integrity algorithm successfully negotiated is stored 135ba11f792STom Joseph * in the authentication algorithm's instance. 136dd1be1a2STom Joseph */ 137dd1be1a2STom Joseph integrity::Algorithms intAlgo; 138ba11f792STom Joseph 1393563f8feSTom Joseph /** 140ba11f792STom Joseph * Confidentiality Algorithm is activated and set in the session data 141ba11f792STom Joseph * only once the session setup is succeeded in the RAKP34 command. But 142ba11f792STom Joseph * the confidentiality algorithm is negotiated in the Open Session 143ba11f792STom Joseph * Request command. So the confidentiality algorithm successfully 144ba11f792STom Joseph * negotiated is stored in the authentication algorithm's instance. 145ba11f792STom Joseph */ 146ba11f792STom Joseph crypt::Algorithms cryptAlgo; 1478c0446c1STom Joseph }; 1488c0446c1STom Joseph 1493563f8feSTom Joseph /** 1508c0446c1STom Joseph * @class AlgoSHA1 1518c0446c1STom Joseph * 1528c0446c1STom Joseph * RAKP-HMAC-SHA1 specifies the use of RAKP messages for the key exchange 1538c0446c1STom Joseph * portion of establishing the session, and that HMAC-SHA1 (per [RFC2104]) is 1548c0446c1STom Joseph * used to create 20-byte Key Exchange Authentication Code fields in RAKP 1558c0446c1STom Joseph * Message 2 and RAKP Message 3. HMAC-SHA1-96(per [RFC2404]) is used for 1568c0446c1STom Joseph * generating a 12-byte Integrity Check Value field for RAKP Message 4. 1578c0446c1STom Joseph */ 1588c0446c1STom Joseph 1598c0446c1STom Joseph class AlgoSHA1 : public Interface 1608c0446c1STom Joseph { 1618c0446c1STom Joseph public: 1622207f51cSVernon Mauery static constexpr size_t integrityCheckValueLength = 12; 1632207f51cSVernon Mauery AlgoSHA1(integrity::Algorithms intAlgo,crypt::Algorithms cryptAlgo)164ba11f792STom Joseph explicit AlgoSHA1(integrity::Algorithms intAlgo, 165ba11f792STom Joseph crypt::Algorithms cryptAlgo) : 1669e801a2bSVernon Mauery Interface(intAlgo, cryptAlgo) 167bc8958feSGeorge Liu {} 168ba11f792STom Joseph 169dd1be1a2STom Joseph AlgoSHA1() = delete; 1708c0446c1STom Joseph ~AlgoSHA1() = default; 1718c0446c1STom Joseph AlgoSHA1(const AlgoSHA1&) = default; 1728c0446c1STom Joseph AlgoSHA1& operator=(const AlgoSHA1&) = default; 1738c0446c1STom Joseph AlgoSHA1(AlgoSHA1&&) = default; 1748c0446c1STom Joseph AlgoSHA1& operator=(AlgoSHA1&&) = default; 1758c0446c1STom Joseph 176*33503e2aSPatrick Williams std::vector<uint8_t> generateHMAC( 177*33503e2aSPatrick Williams const std::vector<uint8_t>& input) const override; 1788c0446c1STom Joseph 179*33503e2aSPatrick Williams std::vector<uint8_t> generateICV( 180*33503e2aSPatrick Williams const std::vector<uint8_t>& input) const override; 1818c0446c1STom Joseph }; 1828c0446c1STom Joseph 1837e9e2ef6SVernon Mauery /** 1847e9e2ef6SVernon Mauery * @class AlgoSHA256 1857e9e2ef6SVernon Mauery * 1867e9e2ef6SVernon Mauery * RAKP-HMAC-SHA256 specifies the use of RAKP messages for the key exchange 1877e9e2ef6SVernon Mauery * portion of establishing the session, and that HMAC-SHA256 (per [FIPS 180-2] 1887e9e2ef6SVernon Mauery * and [RFC4634] and is used to create a 32-byte Key Exchange Authentication 1897e9e2ef6SVernon Mauery * Code fields in RAKP Message 2 and RAKP Message 3. HMAC-SHA256-128 (per 1907e9e2ef6SVernon Mauery * [RFC4868]) is used for generating a 16-byte Integrity Check Value field for 1917e9e2ef6SVernon Mauery * RAKP Message 4. 1927e9e2ef6SVernon Mauery */ 1937e9e2ef6SVernon Mauery 1947e9e2ef6SVernon Mauery class AlgoSHA256 : public Interface 1957e9e2ef6SVernon Mauery { 1967e9e2ef6SVernon Mauery public: 1977e9e2ef6SVernon Mauery static constexpr size_t integrityCheckValueLength = 16; 1987e9e2ef6SVernon Mauery AlgoSHA256(integrity::Algorithms intAlgo,crypt::Algorithms cryptAlgo)1997e9e2ef6SVernon Mauery explicit AlgoSHA256(integrity::Algorithms intAlgo, 2007e9e2ef6SVernon Mauery crypt::Algorithms cryptAlgo) : 2019e801a2bSVernon Mauery Interface(intAlgo, cryptAlgo) 202bc8958feSGeorge Liu {} 2037e9e2ef6SVernon Mauery 2047e9e2ef6SVernon Mauery ~AlgoSHA256() = default; 2057e9e2ef6SVernon Mauery AlgoSHA256(const AlgoSHA256&) = default; 2067e9e2ef6SVernon Mauery AlgoSHA256& operator=(const AlgoSHA256&) = default; 2077e9e2ef6SVernon Mauery AlgoSHA256(AlgoSHA256&&) = default; 2087e9e2ef6SVernon Mauery AlgoSHA256& operator=(AlgoSHA256&&) = default; 2097e9e2ef6SVernon Mauery 210*33503e2aSPatrick Williams std::vector<uint8_t> generateHMAC( 211*33503e2aSPatrick Williams const std::vector<uint8_t>& input) const override; 2127e9e2ef6SVernon Mauery 213*33503e2aSPatrick Williams std::vector<uint8_t> generateICV( 214*33503e2aSPatrick Williams const std::vector<uint8_t>& input) const override; 2157e9e2ef6SVernon Mauery }; 2167e9e2ef6SVernon Mauery 2179e801a2bSVernon Mauery } // namespace rakp_auth 2188c0446c1STom Joseph 2198c0446c1STom Joseph } // namespace cipher 220