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;
1856527b93STom Joseph extern const std::string userName;
198c0446c1STom Joseph 
203563f8feSTom Joseph /**
218c0446c1STom Joseph  * @enum RAKP Authentication Algorithms
228c0446c1STom Joseph  *
238c0446c1STom Joseph  * RMCP+ Authenticated Key-Exchange Protocol (RAKP)
248c0446c1STom Joseph  *
258c0446c1STom Joseph  * RAKP-None is not supported as per the following recommendation
268c0446c1STom Joseph  * (https://www.us-cert.gov/ncas/alerts/TA13-207A)
278c0446c1STom Joseph  * ("cipher 0" is an option enabled by default on many IPMI enabled devices that
288c0446c1STom Joseph  * allows authentication to be bypassed.  Disable "cipher 0" to prevent
298c0446c1STom Joseph  * attackers from bypassing authentication and sending arbitrary IPMI commands.)
308c0446c1STom Joseph  */
318c0446c1STom Joseph enum class Algorithms : uint8_t
328c0446c1STom Joseph {
33fe5a6458STom Joseph     RAKP_NONE = 0,    // Mandatory (implemented, not supported)
34fe5a6458STom Joseph     RAKP_HMAC_SHA1,   // Mandatory (implemented, default choice in ipmitool)
35fe5a6458STom Joseph     RAKP_HMAC_MD5,    // Optional (not implemented)
36fe5a6458STom Joseph     RAKP_HMAC_SHA256, // Optional (implemented, best available)
378c0446c1STom Joseph     // Reserved used to indicate an invalid authentication algorithm
388c0446c1STom Joseph     RAKP_HMAC_INVALID = 0xB0
398c0446c1STom Joseph };
408c0446c1STom Joseph 
413563f8feSTom Joseph /**
428c0446c1STom Joseph  * @class Interface
438c0446c1STom Joseph  *
448c0446c1STom Joseph  * Interface is the base class for the Authentication Algorithms.
458c0446c1STom Joseph  * The Authentication Algorithm specifies the type of authentication “handshake”
468c0446c1STom Joseph  * process that is used and identifies any particular variations of hashing or
478c0446c1STom Joseph  * signature algorithm that is used as part of the process.
488c0446c1STom Joseph  *
498c0446c1STom Joseph  */
508c0446c1STom Joseph class Interface
518c0446c1STom Joseph {
528c0446c1STom Joseph   public:
Interface(integrity::Algorithms intAlgo,crypt::Algorithms cryptAlgo)53ba11f792STom Joseph     explicit Interface(integrity::Algorithms intAlgo,
54ba11f792STom Joseph                        crypt::Algorithms cryptAlgo) :
55ba11f792STom Joseph         intAlgo(intAlgo),
569e801a2bSVernon Mauery         cryptAlgo(cryptAlgo)
57*bc8958feSGeorge Liu     {}
58ba11f792STom Joseph 
59dd1be1a2STom Joseph     Interface() = delete;
608c0446c1STom Joseph     virtual ~Interface() = default;
618c0446c1STom Joseph     Interface(const Interface&) = default;
628c0446c1STom Joseph     Interface& operator=(const Interface&) = default;
638c0446c1STom Joseph     Interface(Interface&&) = default;
648c0446c1STom Joseph     Interface& operator=(Interface&&) = default;
658c0446c1STom Joseph 
663563f8feSTom Joseph     /**
678c0446c1STom Joseph      * @brief Generate the Hash Message Authentication Code
688c0446c1STom Joseph      *
698c0446c1STom Joseph      * This API is invoked to generate the Key Exchange Authentication Code
708c0446c1STom Joseph      * in the RAKP2 and RAKP4 sequence and for generating the Session
718c0446c1STom Joseph      * Integrity Key.
728c0446c1STom Joseph      *
738c0446c1STom Joseph      * @param input message
748c0446c1STom Joseph      *
758c0446c1STom Joseph      * @return hash output
768c0446c1STom Joseph      *
778c0446c1STom Joseph      * @note The user key which is the secret key for the hash operation
788c0446c1STom Joseph      *        needs to be set before this operation.
798c0446c1STom Joseph      */
808c0446c1STom Joseph     std::vector<uint8_t> virtual generateHMAC(
8170fd29cfSVernon Mauery         const std::vector<uint8_t>& input) const = 0;
828c0446c1STom Joseph 
833563f8feSTom Joseph     /**
848c0446c1STom Joseph      * @brief Generate the Integrity Check Value
858c0446c1STom Joseph      *
868c0446c1STom Joseph      * This API is invoked in the RAKP4 sequence for generating the
878c0446c1STom Joseph      * Integrity Check Value.
888c0446c1STom Joseph      *
898c0446c1STom Joseph      * @param input message
908c0446c1STom Joseph      *
918c0446c1STom Joseph      * @return hash output
928c0446c1STom Joseph      *
938c0446c1STom Joseph      * @note The session integrity key which is the secret key for the
948c0446c1STom Joseph      *        hash operation needs to be set before this operation.
958c0446c1STom Joseph      */
968c0446c1STom Joseph     std::vector<uint8_t> virtual generateICV(
9770fd29cfSVernon Mauery         const std::vector<uint8_t>& input) const = 0;
988c0446c1STom Joseph 
999b307be6SVernon Mauery     /**
1009b307be6SVernon Mauery      * @brief Check if the Authentication algorithm is supported
1019b307be6SVernon Mauery      *
1029b307be6SVernon Mauery      * @param[in] algo - authentication algorithm
1039b307be6SVernon Mauery      *
1049b307be6SVernon Mauery      * @return true if algorithm is supported else false
1059b307be6SVernon Mauery      *
1069b307be6SVernon Mauery      */
isAlgorithmSupported(Algorithms algo)1079b307be6SVernon Mauery     static bool isAlgorithmSupported(Algorithms algo)
1089b307be6SVernon Mauery     {
1094c494398SSuryakanth Sekar         if (algo == Algorithms::RAKP_HMAC_SHA256)
1109b307be6SVernon Mauery         {
1119b307be6SVernon Mauery             return true;
1129b307be6SVernon Mauery         }
1139b307be6SVernon Mauery         else
1149b307be6SVernon Mauery         {
1159b307be6SVernon Mauery             return false;
1169b307be6SVernon Mauery         }
1179b307be6SVernon Mauery     }
1189b307be6SVernon Mauery 
1198c0446c1STom Joseph     // User Key is hardcoded to PASSW0RD till the IPMI User account
1208c0446c1STom Joseph     // management is in place.
121e2e97660STom Joseph     std::array<uint8_t, USER_KEY_MAX_LENGTH> userKey = {"0penBmc"};
1228c0446c1STom Joseph 
1238c0446c1STom Joseph     // Managed System Random Number
1248c0446c1STom Joseph     std::array<uint8_t, BMC_RANDOM_NUMBER_LEN> bmcRandomNum;
1258c0446c1STom Joseph 
1268c0446c1STom Joseph     // Remote Console Random Number
1278c0446c1STom Joseph     std::array<uint8_t, REMOTE_CONSOLE_RANDOM_NUMBER_LEN> rcRandomNum;
1288c0446c1STom Joseph 
1298c0446c1STom Joseph     // Session Integrity Key
1308c0446c1STom Joseph     std::vector<uint8_t> sessionIntegrityKey;
131dd1be1a2STom Joseph 
1323563f8feSTom Joseph     /**
133dd1be1a2STom Joseph      * Integrity Algorithm is activated and set in the session data only
134dd1be1a2STom Joseph      * once the session setup is succeeded in the RAKP34 command. But the
135dd1be1a2STom Joseph      * integrity algorithm is negotiated in the Open Session Request command
136ba11f792STom Joseph      * . So the integrity algorithm successfully negotiated is stored
137ba11f792STom Joseph      * in the authentication algorithm's instance.
138dd1be1a2STom Joseph      */
139dd1be1a2STom Joseph     integrity::Algorithms intAlgo;
140ba11f792STom Joseph 
1413563f8feSTom Joseph     /**
142ba11f792STom Joseph      * Confidentiality Algorithm is activated and set in the session data
143ba11f792STom Joseph      * only once the session setup is succeeded in the RAKP34 command. But
144ba11f792STom Joseph      * the confidentiality algorithm is negotiated in the Open Session
145ba11f792STom Joseph      * Request command. So the confidentiality algorithm successfully
146ba11f792STom Joseph      * negotiated is stored in the authentication algorithm's instance.
147ba11f792STom Joseph      */
148ba11f792STom Joseph     crypt::Algorithms cryptAlgo;
1498c0446c1STom Joseph };
1508c0446c1STom Joseph 
1513563f8feSTom Joseph /**
1528c0446c1STom Joseph  * @class AlgoSHA1
1538c0446c1STom Joseph  *
1548c0446c1STom Joseph  * RAKP-HMAC-SHA1 specifies the use of RAKP messages for the key exchange
1558c0446c1STom Joseph  * portion of establishing the session, and that HMAC-SHA1 (per [RFC2104]) is
1568c0446c1STom Joseph  * used to create 20-byte Key Exchange Authentication Code fields in RAKP
1578c0446c1STom Joseph  * Message 2 and RAKP Message 3. HMAC-SHA1-96(per [RFC2404]) is used for
1588c0446c1STom Joseph  * generating a 12-byte Integrity Check Value field for RAKP Message 4.
1598c0446c1STom Joseph  */
1608c0446c1STom Joseph 
1618c0446c1STom Joseph class AlgoSHA1 : public Interface
1628c0446c1STom Joseph {
1638c0446c1STom Joseph   public:
1642207f51cSVernon Mauery     static constexpr size_t integrityCheckValueLength = 12;
1652207f51cSVernon Mauery 
AlgoSHA1(integrity::Algorithms intAlgo,crypt::Algorithms cryptAlgo)166ba11f792STom Joseph     explicit AlgoSHA1(integrity::Algorithms intAlgo,
167ba11f792STom Joseph                       crypt::Algorithms cryptAlgo) :
1689e801a2bSVernon Mauery         Interface(intAlgo, cryptAlgo)
169*bc8958feSGeorge Liu     {}
170ba11f792STom Joseph 
171dd1be1a2STom Joseph     AlgoSHA1() = delete;
1728c0446c1STom Joseph     ~AlgoSHA1() = default;
1738c0446c1STom Joseph     AlgoSHA1(const AlgoSHA1&) = default;
1748c0446c1STom Joseph     AlgoSHA1& operator=(const AlgoSHA1&) = default;
1758c0446c1STom Joseph     AlgoSHA1(AlgoSHA1&&) = default;
1768c0446c1STom Joseph     AlgoSHA1& operator=(AlgoSHA1&&) = default;
1778c0446c1STom Joseph 
1789e801a2bSVernon Mauery     std::vector<uint8_t>
1799e801a2bSVernon Mauery         generateHMAC(const std::vector<uint8_t>& input) const override;
1808c0446c1STom Joseph 
1819e801a2bSVernon Mauery     std::vector<uint8_t>
1829e801a2bSVernon Mauery         generateICV(const std::vector<uint8_t>& input) const override;
1838c0446c1STom Joseph };
1848c0446c1STom Joseph 
1857e9e2ef6SVernon Mauery /**
1867e9e2ef6SVernon Mauery  * @class AlgoSHA256
1877e9e2ef6SVernon Mauery  *
1887e9e2ef6SVernon Mauery  * RAKP-HMAC-SHA256 specifies the use of RAKP messages for the key exchange
1897e9e2ef6SVernon Mauery  * portion of establishing the session, and that HMAC-SHA256 (per [FIPS 180-2]
1907e9e2ef6SVernon Mauery  * and [RFC4634] and is used to create a 32-byte Key Exchange Authentication
1917e9e2ef6SVernon Mauery  * Code fields in RAKP Message 2 and RAKP Message 3. HMAC-SHA256-128 (per
1927e9e2ef6SVernon Mauery  * [RFC4868]) is used for generating a 16-byte Integrity Check Value field for
1937e9e2ef6SVernon Mauery  * RAKP Message 4.
1947e9e2ef6SVernon Mauery  */
1957e9e2ef6SVernon Mauery 
1967e9e2ef6SVernon Mauery class AlgoSHA256 : public Interface
1977e9e2ef6SVernon Mauery {
1987e9e2ef6SVernon Mauery   public:
1997e9e2ef6SVernon Mauery     static constexpr size_t integrityCheckValueLength = 16;
2007e9e2ef6SVernon Mauery 
AlgoSHA256(integrity::Algorithms intAlgo,crypt::Algorithms cryptAlgo)2017e9e2ef6SVernon Mauery     explicit AlgoSHA256(integrity::Algorithms intAlgo,
2027e9e2ef6SVernon Mauery                         crypt::Algorithms cryptAlgo) :
2039e801a2bSVernon Mauery         Interface(intAlgo, cryptAlgo)
204*bc8958feSGeorge Liu     {}
2057e9e2ef6SVernon Mauery 
2067e9e2ef6SVernon Mauery     ~AlgoSHA256() = default;
2077e9e2ef6SVernon Mauery     AlgoSHA256(const AlgoSHA256&) = default;
2087e9e2ef6SVernon Mauery     AlgoSHA256& operator=(const AlgoSHA256&) = default;
2097e9e2ef6SVernon Mauery     AlgoSHA256(AlgoSHA256&&) = default;
2107e9e2ef6SVernon Mauery     AlgoSHA256& operator=(AlgoSHA256&&) = default;
2117e9e2ef6SVernon Mauery 
2129e801a2bSVernon Mauery     std::vector<uint8_t>
2139e801a2bSVernon Mauery         generateHMAC(const std::vector<uint8_t>& input) const override;
2147e9e2ef6SVernon Mauery 
2159e801a2bSVernon Mauery     std::vector<uint8_t>
2169e801a2bSVernon Mauery         generateICV(const std::vector<uint8_t>& input) const override;
2177e9e2ef6SVernon Mauery };
2187e9e2ef6SVernon Mauery 
2199e801a2bSVernon Mauery } // namespace rakp_auth
2208c0446c1STom Joseph 
2218c0446c1STom Joseph } // namespace cipher
222