xref: /openbmc/phosphor-net-ipmid/integrity_algo.hpp (revision bac2f1a31eb5d2613ae11b220b28764484d7c06c)
177531db5STom Joseph #pragma once
277531db5STom Joseph 
39e801a2bSVernon Mauery #include "rmcp.hpp"
49e801a2bSVernon Mauery 
577531db5STom Joseph #include <array>
69d9b7638SAndrew Geissler #include <cstddef>
777531db5STom Joseph #include <vector>
877531db5STom Joseph 
977531db5STom Joseph namespace cipher
1077531db5STom Joseph {
1177531db5STom Joseph 
1277531db5STom Joseph namespace integrity
1377531db5STom Joseph {
1477531db5STom Joseph 
153563f8feSTom Joseph /**
1677531db5STom Joseph  * @enum Integrity Algorithms
1777531db5STom Joseph  *
1877531db5STom Joseph  * The Integrity Algorithm Number specifies the algorithm used to generate the
1977531db5STom Joseph  * contents for the AuthCode “signature” field that accompanies authenticated
2077531db5STom Joseph  * IPMI v2.0/RMCP+ messages once the session has been established. If the
2177531db5STom Joseph  * Integrity Algorithm is none the AuthCode value is not calculated and the
22fe5a6458STom Joseph  * AuthCode field in the message is not present. Based on security
23fe5a6458STom Joseph  * recommendations NONE will not be supported.
2477531db5STom Joseph  */
2577531db5STom Joseph enum class Algorithms : uint8_t
2677531db5STom Joseph {
27fe5a6458STom Joseph     NONE,            // Mandatory (implemented, not supported)
28fe5a6458STom Joseph     HMAC_SHA1_96,    // Mandatory (implemented, default choice in ipmitool)
29fe5a6458STom Joseph     HMAC_MD5_128,    // Optional (not implemented)
30fe5a6458STom Joseph     MD5_128,         // Optional (not implemented)
31fe5a6458STom Joseph     HMAC_SHA256_128, // Optional (implemented, best available)
3277531db5STom Joseph };
3377531db5STom Joseph 
343563f8feSTom Joseph /**
3577531db5STom Joseph  * @class Interface
3677531db5STom Joseph  *
3777531db5STom Joseph  * Interface is the base class for the Integrity Algorithms.
3877531db5STom Joseph  * Unless otherwise specified, the integrity algorithm is applied to the packet
3977531db5STom Joseph  * data starting with the AuthType/Format field up to and including the field
4077531db5STom Joseph  * that immediately precedes the AuthCode field itself.
4177531db5STom Joseph  */
4277531db5STom Joseph class Interface
4377531db5STom Joseph {
4477531db5STom Joseph   public:
453563f8feSTom Joseph     /**
4677531db5STom Joseph      * @brief Constructor for Interface
4777531db5STom Joseph      *
4877531db5STom Joseph      * @param[in] - AuthCode length
4977531db5STom Joseph      */
Interface(size_t authLength)50099fb097SPatrick Williams     explicit Interface(size_t authLength) : authCodeLength(authLength) {}
5177531db5STom Joseph 
5277531db5STom Joseph     Interface() = delete;
5377531db5STom Joseph     virtual ~Interface() = default;
5477531db5STom Joseph     Interface(const Interface&) = default;
5577531db5STom Joseph     Interface& operator=(const Interface&) = default;
5677531db5STom Joseph     Interface(Interface&&) = default;
5777531db5STom Joseph     Interface& operator=(Interface&&) = default;
5877531db5STom Joseph 
593563f8feSTom Joseph     /**
6077531db5STom Joseph      * @brief Verify the integrity data of the packet
6177531db5STom Joseph      *
6277531db5STom Joseph      * @param[in] packet - Incoming IPMI packet
6377531db5STom Joseph      * @param[in] packetLen - Packet length excluding authCode
64198b0f81SGeorge Liu      * @param[in] integrityDataBegin - Begin iterator to the authCode in the
65198b0f81SGeorge Liu      *                                 packet
66198b0f81SGeorge Liu      * @param[in] integrityDataEnd   - End to the authCode in the packet
6777531db5STom Joseph      *
6877531db5STom Joseph      * @return true if authcode in the packet is equal to one generated
6977531db5STom Joseph      *         using integrity algorithm on the packet data, false otherwise
7077531db5STom Joseph      */
7177531db5STom Joseph     bool virtual verifyIntegrityData(
729e801a2bSVernon Mauery         const std::vector<uint8_t>& packet, const size_t packetLen,
73198b0f81SGeorge Liu         std::vector<uint8_t>::const_iterator integrityDataBegin,
74198b0f81SGeorge Liu         std::vector<uint8_t>::const_iterator integrityDataEnd) const = 0;
7577531db5STom Joseph 
763563f8feSTom Joseph     /**
7777531db5STom Joseph      * @brief Generate integrity data for the outgoing IPMI packet
7877531db5STom Joseph      *
7977531db5STom Joseph      * @param[in] input - Outgoing IPMI packet
8077531db5STom Joseph      *
8177531db5STom Joseph      * @return authcode for the outgoing IPMI packet
8277531db5STom Joseph      *
8377531db5STom Joseph      */
8470fd29cfSVernon Mauery     std::vector<uint8_t> virtual generateIntegrityData(
8570fd29cfSVernon Mauery         const std::vector<uint8_t>& input) const = 0;
8677531db5STom Joseph 
871e7aa196STom Joseph     /**
881e7aa196STom Joseph      * @brief Check if the Integrity algorithm is supported
891e7aa196STom Joseph      *
901e7aa196STom Joseph      * @param[in] algo - integrity algorithm
911e7aa196STom Joseph      *
921e7aa196STom Joseph      * @return true if algorithm is supported else false
931e7aa196STom Joseph      *
941e7aa196STom Joseph      */
isAlgorithmSupported(Algorithms algo)951e7aa196STom Joseph     static bool isAlgorithmSupported(Algorithms algo)
961e7aa196STom Joseph     {
974c494398SSuryakanth Sekar         if (algo == Algorithms::HMAC_SHA256_128)
981e7aa196STom Joseph         {
991e7aa196STom Joseph             return true;
1001e7aa196STom Joseph         }
1011e7aa196STom Joseph         else
1021e7aa196STom Joseph         {
1031e7aa196STom Joseph             return false;
1041e7aa196STom Joseph         }
1051e7aa196STom Joseph     }
1061e7aa196STom Joseph 
1079b307be6SVernon Mauery     /**
1089b307be6SVernon Mauery      * @brief Generate additional keying material based on SIK
1099b307be6SVernon Mauery      *
1109b307be6SVernon Mauery      * @note
1119b307be6SVernon Mauery      * The IPMI 2.0 spec only states that the additional keying material is
1129b307be6SVernon Mauery      * generated by running HMAC(constN) using SIK as the key. It does not
1139b307be6SVernon Mauery      * state whether this is the integrity algorithm or the authentication
1149b307be6SVernon Mauery      * algorithm. Other implementations of the RMCP+ algorithm (ipmitool
1159b307be6SVernon Mauery      * and ipmiutil) are not consistent on this matter. But it does not
1169b307be6SVernon Mauery      * really matter because based on any of the defined cipher suites, the
1179b307be6SVernon Mauery      * integrity and authentication algorithms are both based on the same
1189b307be6SVernon Mauery      * digest method (integrity::Algorithms::HMAC_SHA1_96 uses SHA1 and
1199b307be6SVernon Mauery      * rakp_auth::Algorithms::RAKP_HMAC_SHA1 uses SHA1). None of the
1209b307be6SVernon Mauery      * defined cipher suites mix and match digests for integrity and
1219b307be6SVernon Mauery      * authentication. Generating Kn belongs in either the integrity or
1229b307be6SVernon Mauery      * authentication classes, so in this implementation, integrity has
1239b307be6SVernon Mauery      * been chosen.
1249b307be6SVernon Mauery      *
1259b307be6SVernon Mauery      * @param[in] sik - session integrity key
1269b307be6SVernon Mauery      * @param[in] data - 20-byte Const_n
1279b307be6SVernon Mauery      *
1289b307be6SVernon Mauery      * @return on success returns the Kn based on this integrity class
1299b307be6SVernon Mauery      *
1309b307be6SVernon Mauery      */
1319b307be6SVernon Mauery     std::vector<uint8_t> virtual generateKn(
1329e801a2bSVernon Mauery         const std::vector<uint8_t>& sik, const rmcp::Const_n& data) const = 0;
1339b307be6SVernon Mauery 
1343563f8feSTom Joseph     /** @brief Authcode field
1353563f8feSTom Joseph      *
13677531db5STom Joseph      *  AuthCode field length varies based on the integrity algorithm, for
13777531db5STom Joseph      *  HMAC-SHA1-96 the authcode field is 12 bytes. For HMAC-SHA256-128 and
13877531db5STom Joseph      *  HMAC-MD5-128 the authcode field is 16 bytes.
13977531db5STom Joseph      */
14077531db5STom Joseph     size_t authCodeLength;
14177531db5STom Joseph 
14277531db5STom Joseph   protected:
1433563f8feSTom Joseph     /** @brief K1 key used to generated the integrity data. */
1449b307be6SVernon Mauery     std::vector<uint8_t> k1;
14577531db5STom Joseph };
14677531db5STom Joseph 
1473563f8feSTom Joseph /**
148d212a6dcSTom Joseph  * @class AlgoSHA1
149d212a6dcSTom Joseph  *
150d212a6dcSTom Joseph  * @brief Implementation of the HMAC-SHA1-96 Integrity algorithm
151d212a6dcSTom Joseph  *
152d212a6dcSTom Joseph  * HMAC-SHA1-96 take the Session Integrity Key and use it to generate K1. K1 is
153d212a6dcSTom Joseph  * then used as the key for use in HMAC to produce the AuthCode field.
154d212a6dcSTom Joseph  * For “one-key” logins, the user’s key (password) is used in the creation of
155d212a6dcSTom Joseph  * the Session Integrity Key. When the HMAC-SHA1-96 Integrity Algorithm is used
156d212a6dcSTom Joseph  * the resulting AuthCode field is 12 bytes (96 bits).
157d212a6dcSTom Joseph  */
158d212a6dcSTom Joseph class AlgoSHA1 final : public Interface
159d212a6dcSTom Joseph {
160d212a6dcSTom Joseph   public:
161d212a6dcSTom Joseph     static constexpr size_t SHA1_96_AUTHCODE_LENGTH = 12;
162d212a6dcSTom Joseph 
1633563f8feSTom Joseph     /**
164d212a6dcSTom Joseph      * @brief Constructor for AlgoSHA1
165d212a6dcSTom Joseph      *
166d212a6dcSTom Joseph      * @param[in] - Session Integrity Key
167d212a6dcSTom Joseph      */
1689b307be6SVernon Mauery     explicit AlgoSHA1(const std::vector<uint8_t>& sik);
169d212a6dcSTom Joseph 
170d212a6dcSTom Joseph     AlgoSHA1() = delete;
171d212a6dcSTom Joseph     ~AlgoSHA1() = default;
172d212a6dcSTom Joseph     AlgoSHA1(const AlgoSHA1&) = default;
173d212a6dcSTom Joseph     AlgoSHA1& operator=(const AlgoSHA1&) = default;
174d212a6dcSTom Joseph     AlgoSHA1(AlgoSHA1&&) = default;
175d212a6dcSTom Joseph     AlgoSHA1& operator=(AlgoSHA1&&) = default;
176d212a6dcSTom Joseph 
1773563f8feSTom Joseph     /**
178d212a6dcSTom Joseph      * @brief Verify the integrity data of the packet
179d212a6dcSTom Joseph      *
180d212a6dcSTom Joseph      * @param[in] packet - Incoming IPMI packet
181d212a6dcSTom Joseph      * @param[in] length - Length of the data in the packet to calculate
182d212a6dcSTom Joseph      *                     the integrity data
183198b0f81SGeorge Liu      * @param[in] integrityDataBegin - Begin iterator to the authCode in the
184198b0f81SGeorge Liu      *                                 packet
185198b0f81SGeorge Liu      * @param[in] integrityDataEnd   - End to the authCode in the packet
186d212a6dcSTom Joseph      *
187d212a6dcSTom Joseph      * @return true if authcode in the packet is equal to one generated
188d212a6dcSTom Joseph      *         using integrity algorithm on the packet data, false otherwise
189d212a6dcSTom Joseph      */
190d212a6dcSTom Joseph     bool verifyIntegrityData(
1919e801a2bSVernon Mauery         const std::vector<uint8_t>& packet, const size_t length,
192198b0f81SGeorge Liu         std::vector<uint8_t>::const_iterator integrityDataBegin,
193198b0f81SGeorge Liu         std::vector<uint8_t>::const_iterator integrityDataEnd) const override;
194d212a6dcSTom Joseph 
1953563f8feSTom Joseph     /**
196d212a6dcSTom Joseph      * @brief Generate integrity data for the outgoing IPMI packet
197d212a6dcSTom Joseph      *
198d212a6dcSTom Joseph      * @param[in] input - Outgoing IPMI packet
199d212a6dcSTom Joseph      *
200d212a6dcSTom Joseph      * @return on success return the integrity data for the outgoing IPMI
201d212a6dcSTom Joseph      *         packet
202d212a6dcSTom Joseph      */
20370fd29cfSVernon Mauery     std::vector<uint8_t> generateIntegrityData(
20470fd29cfSVernon Mauery         const std::vector<uint8_t>& packet) const override;
205d212a6dcSTom Joseph 
2069b307be6SVernon Mauery     /**
2079b307be6SVernon Mauery      * @brief Generate additional keying material based on SIK
2089b307be6SVernon Mauery      *
2099b307be6SVernon Mauery      * @param[in] sik - session integrity key
2109b307be6SVernon Mauery      * @param[in] data - 20-byte Const_n
2119b307be6SVernon Mauery      *
2129b307be6SVernon Mauery      * @return on success returns the Kn based on HMAC-SHA1
2139b307be6SVernon Mauery      *
2149b307be6SVernon Mauery      */
215*bac2f1a3SLei YU     std::vector<uint8_t> generateKn(
216*bac2f1a3SLei YU         const std::vector<uint8_t>& sik,
217*bac2f1a3SLei YU         const rmcp::Const_n& const_n) const override;
2189b307be6SVernon Mauery 
219d212a6dcSTom Joseph   private:
2203563f8feSTom Joseph     /**
221d212a6dcSTom Joseph      * @brief Generate HMAC based on HMAC-SHA1-96 algorithm
222d212a6dcSTom Joseph      *
223d212a6dcSTom Joseph      * @param[in] input - pointer to the message
224d212a6dcSTom Joseph      * @param[in] length - length of the message
225d212a6dcSTom Joseph      *
226d212a6dcSTom Joseph      * @return on success returns the message authentication code
227d212a6dcSTom Joseph      *
228d212a6dcSTom Joseph      */
22970fd29cfSVernon Mauery     std::vector<uint8_t> generateHMAC(const uint8_t* input,
23070fd29cfSVernon Mauery                                       const size_t len) const;
231d212a6dcSTom Joseph };
232d212a6dcSTom Joseph 
2337e9e2ef6SVernon Mauery /**
2347e9e2ef6SVernon Mauery  * @class AlgoSHA256
2357e9e2ef6SVernon Mauery  *
2367e9e2ef6SVernon Mauery  * @brief Implementation of the HMAC-SHA256-128 Integrity algorithm
2377e9e2ef6SVernon Mauery  *
2387e9e2ef6SVernon Mauery  * HMAC-SHA256-128 take the Session Integrity Key and use it to generate K1. K1
2397e9e2ef6SVernon Mauery  * is then used as the key for use in HMAC to produce the AuthCode field.  For
2407e9e2ef6SVernon Mauery  * “one-key” logins, the user’s key (password) is used in the creation of the
2417e9e2ef6SVernon Mauery  * Session Integrity Key. When the HMAC-SHA256-128 Integrity Algorithm is used
2427e9e2ef6SVernon Mauery  * the resulting AuthCode field is 16 bytes (128 bits).
2437e9e2ef6SVernon Mauery  */
2447e9e2ef6SVernon Mauery class AlgoSHA256 final : public Interface
2457e9e2ef6SVernon Mauery {
2467e9e2ef6SVernon Mauery   public:
2477e9e2ef6SVernon Mauery     static constexpr size_t SHA256_128_AUTHCODE_LENGTH = 16;
2487e9e2ef6SVernon Mauery 
2497e9e2ef6SVernon Mauery     /**
2507e9e2ef6SVernon Mauery      * @brief Constructor for AlgoSHA256
2517e9e2ef6SVernon Mauery      *
2527e9e2ef6SVernon Mauery      * @param[in] - Session Integrity Key
2537e9e2ef6SVernon Mauery      */
2547e9e2ef6SVernon Mauery     explicit AlgoSHA256(const std::vector<uint8_t>& sik);
2557e9e2ef6SVernon Mauery 
2567e9e2ef6SVernon Mauery     AlgoSHA256() = delete;
2577e9e2ef6SVernon Mauery     ~AlgoSHA256() = default;
2587e9e2ef6SVernon Mauery     AlgoSHA256(const AlgoSHA256&) = default;
2597e9e2ef6SVernon Mauery     AlgoSHA256& operator=(const AlgoSHA256&) = default;
2607e9e2ef6SVernon Mauery     AlgoSHA256(AlgoSHA256&&) = default;
2617e9e2ef6SVernon Mauery     AlgoSHA256& operator=(AlgoSHA256&&) = default;
2627e9e2ef6SVernon Mauery 
2637e9e2ef6SVernon Mauery     /**
2647e9e2ef6SVernon Mauery      * @brief Verify the integrity data of the packet
2657e9e2ef6SVernon Mauery      *
2667e9e2ef6SVernon Mauery      * @param[in] packet - Incoming IPMI packet
2677e9e2ef6SVernon Mauery      * @param[in] length - Length of the data in the packet to calculate
2687e9e2ef6SVernon Mauery      *                     the integrity data
269198b0f81SGeorge Liu      * @param[in] integrityDataBegin - Begin iterator to the authCode in the
270198b0f81SGeorge Liu      *                                 packet
271198b0f81SGeorge Liu      * @param[in] integrityDataEnd   - End to the authCode in the packet
2727e9e2ef6SVernon Mauery      *
2737e9e2ef6SVernon Mauery      * @return true if authcode in the packet is equal to one generated
2747e9e2ef6SVernon Mauery      *         using integrity algorithm on the packet data, false otherwise
2757e9e2ef6SVernon Mauery      */
2767e9e2ef6SVernon Mauery     bool verifyIntegrityData(
2779e801a2bSVernon Mauery         const std::vector<uint8_t>& packet, const size_t length,
278198b0f81SGeorge Liu         std::vector<uint8_t>::const_iterator integrityDataBegin,
279198b0f81SGeorge Liu         std::vector<uint8_t>::const_iterator integrityDataEnd) const override;
2807e9e2ef6SVernon Mauery 
2817e9e2ef6SVernon Mauery     /**
2827e9e2ef6SVernon Mauery      * @brief Generate integrity data for the outgoing IPMI packet
2837e9e2ef6SVernon Mauery      *
2847e9e2ef6SVernon Mauery      * @param[in] packet - Outgoing IPMI packet
2857e9e2ef6SVernon Mauery      *
2867e9e2ef6SVernon Mauery      * @return on success return the integrity data for the outgoing IPMI
2877e9e2ef6SVernon Mauery      *         packet
2887e9e2ef6SVernon Mauery      */
2897e9e2ef6SVernon Mauery     std::vector<uint8_t> generateIntegrityData(
2907e9e2ef6SVernon Mauery         const std::vector<uint8_t>& packet) const override;
2917e9e2ef6SVernon Mauery 
2927e9e2ef6SVernon Mauery     /**
2937e9e2ef6SVernon Mauery      * @brief Generate additional keying material based on SIK
2947e9e2ef6SVernon Mauery      *
2957e9e2ef6SVernon Mauery      * @param[in] sik - session integrity key
2967e9e2ef6SVernon Mauery      * @param[in] data - 20-byte Const_n
2977e9e2ef6SVernon Mauery      *
2987e9e2ef6SVernon Mauery      * @return on success returns the Kn based on HMAC-SHA256
2997e9e2ef6SVernon Mauery      *
3007e9e2ef6SVernon Mauery      */
301*bac2f1a3SLei YU     std::vector<uint8_t> generateKn(
302*bac2f1a3SLei YU         const std::vector<uint8_t>& sik,
303*bac2f1a3SLei YU         const rmcp::Const_n& const_n) const override;
3047e9e2ef6SVernon Mauery 
3057e9e2ef6SVernon Mauery   private:
3067e9e2ef6SVernon Mauery     /**
3077e9e2ef6SVernon Mauery      * @brief Generate HMAC based on HMAC-SHA256-128 algorithm
3087e9e2ef6SVernon Mauery      *
3097e9e2ef6SVernon Mauery      * @param[in] input - pointer to the message
3107e9e2ef6SVernon Mauery      * @param[in] len - length of the message
3117e9e2ef6SVernon Mauery      *
3127e9e2ef6SVernon Mauery      * @return on success returns the message authentication code
3137e9e2ef6SVernon Mauery      *
3147e9e2ef6SVernon Mauery      */
3157e9e2ef6SVernon Mauery     std::vector<uint8_t> generateHMAC(const uint8_t* input,
3167e9e2ef6SVernon Mauery                                       const size_t len) const;
3177e9e2ef6SVernon Mauery };
3187e9e2ef6SVernon Mauery 
31977531db5STom Joseph } // namespace integrity
32077531db5STom Joseph 
32177531db5STom Joseph } // namespace cipher
322