14e57adabSTom Joseph #pragma once 24e57adabSTom Joseph 34e57adabSTom Joseph #include "message.hpp" 44e57adabSTom Joseph #include "session.hpp" 54e57adabSTom Joseph 69d9b7638SAndrew Geissler #include <cstddef> 79d9b7638SAndrew Geissler 84e57adabSTom Joseph namespace message 94e57adabSTom Joseph { 104e57adabSTom Joseph 114e57adabSTom Joseph namespace parser 124e57adabSTom Joseph { 134e57adabSTom Joseph 144e57adabSTom Joseph constexpr size_t RMCP_VERSION = 6; 154e57adabSTom Joseph 164e57adabSTom Joseph // RMCP Messages with class=IPMI should be sent with an RMCP Sequence 174e57adabSTom Joseph // Number of FFh to indicate that an RMCP ACK message should not be 184e57adabSTom Joseph // generated by the message receiver. 194e57adabSTom Joseph constexpr size_t RMCP_SEQ = 0xFF; 204e57adabSTom Joseph 214e57adabSTom Joseph // RMCP Message Class 7h is for IPMI 224e57adabSTom Joseph constexpr size_t RMCP_MESSAGE_CLASS_IPMI = 7; 234e57adabSTom Joseph 2464703f4dSTom Joseph // RMCP Session Header Size 2564703f4dSTom Joseph constexpr size_t RMCP_SESSION_HEADER_SIZE = 4; 2664703f4dSTom Joseph 27de7dd5ceSKirill Pakhomov // RMCP/ASF Pong Message ASF Header Data Length 28de7dd5ceSKirill Pakhomov // as per IPMI spec 13.2.4 29de7dd5ceSKirill Pakhomov constexpr size_t RMCP_ASF_PONG_DATA_LEN = 16; 30de7dd5ceSKirill Pakhomov 31de7dd5ceSKirill Pakhomov // ASF IANA 32de7dd5ceSKirill Pakhomov constexpr uint32_t ASF_IANA = 4542; 33de7dd5ceSKirill Pakhomov 34de7dd5ceSKirill Pakhomov // ASF Supported Entities 35de7dd5ceSKirill Pakhomov constexpr uint32_t ASF_SUPP_ENT = 0x81; 36de7dd5ceSKirill Pakhomov 37de7dd5ceSKirill Pakhomov // ASF Supported Entities 38de7dd5ceSKirill Pakhomov constexpr uint32_t ASF_SUPP_INT = 0x00; 39de7dd5ceSKirill Pakhomov 401efcb493STom Joseph // Maximum payload size 411efcb493STom Joseph constexpr size_t MAX_PAYLOAD_SIZE = 255; 421efcb493STom Joseph 434e57adabSTom Joseph enum class SessionHeader 444e57adabSTom Joseph { 454e57adabSTom Joseph IPMI15 = 0x00, 464e57adabSTom Joseph IPMI20 = 0x06, 474e57adabSTom Joseph INVALID = 0xFF, 484e57adabSTom Joseph }; 494e57adabSTom Joseph 50de7dd5ceSKirill Pakhomov // RMCP Header 51de7dd5ceSKirill Pakhomov struct RmcpHeader_t 524e57adabSTom Joseph { 534e57adabSTom Joseph // RMCP Header 544e57adabSTom Joseph uint8_t version; 554e57adabSTom Joseph uint8_t reserved; 564e57adabSTom Joseph uint8_t rmcpSeqNum; 574e57adabSTom Joseph uint8_t classOfMsg; 58de7dd5ceSKirill Pakhomov } __attribute__((packed)); 59de7dd5ceSKirill Pakhomov 60de7dd5ceSKirill Pakhomov struct BasicHeader_t 61de7dd5ceSKirill Pakhomov { 62de7dd5ceSKirill Pakhomov // RMCP Header 63de7dd5ceSKirill Pakhomov struct RmcpHeader_t rmcp; 644e57adabSTom Joseph 654e57adabSTom Joseph // IPMI partial session header 664e57adabSTom Joseph union 674e57adabSTom Joseph { 684e57adabSTom Joseph uint8_t reserved1:4; 694e57adabSTom Joseph uint8_t authType:4; 704e57adabSTom Joseph uint8_t formatType; 714e57adabSTom Joseph } format; 724e57adabSTom Joseph } __attribute__((packed)); 734e57adabSTom Joseph 743563f8feSTom Joseph /** 754e57adabSTom Joseph * @brief Unflatten an incoming packet and prepare the IPMI message 764e57adabSTom Joseph * 774e57adabSTom Joseph * @param[in] inPacket - Incoming IPMI packet 784e57adabSTom Joseph * 794e57adabSTom Joseph * @return A tuple with IPMI message and the session header type to sent the 804e57adabSTom Joseph * response packet. In case of success incoming message and session 814e57adabSTom Joseph * header type. In case of failure nullptr and session header type 824e57adabSTom Joseph * would be invalid. 834e57adabSTom Joseph */ 84*33503e2aSPatrick Williams std::tuple<std::shared_ptr<Message>, SessionHeader> unflatten( 85*33503e2aSPatrick Williams std::vector<uint8_t>& inPacket); 864e57adabSTom Joseph 873563f8feSTom Joseph /** 884e57adabSTom Joseph * @brief Flatten an IPMI message and generate the IPMI packet with the 894e57adabSTom Joseph * session header 904e57adabSTom Joseph * 914e57adabSTom Joseph * @param[in] outMessage - IPMI message to be flattened 924e57adabSTom Joseph * @param[in] authType - Session header type to be added to the IPMI 934e57adabSTom Joseph * packet 944e57adabSTom Joseph * 954e57adabSTom Joseph * @return IPMI packet on success 964e57adabSTom Joseph */ 97a82e4d3eSLei YU std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage, 98224f36a4SVernon Mauery SessionHeader authType, 99a82e4d3eSLei YU const std::shared_ptr<session::Session>& session); 1004e57adabSTom Joseph 1014e57adabSTom Joseph } // namespace parser 1024e57adabSTom Joseph 1034e57adabSTom Joseph namespace ipmi15parser 1044e57adabSTom Joseph { 1054e57adabSTom Joseph 1064e57adabSTom Joseph struct SessionHeader_t 1074e57adabSTom Joseph { 1084e57adabSTom Joseph struct parser::BasicHeader_t base; 1094e57adabSTom Joseph uint32_t sessSeqNum; 1104e57adabSTom Joseph uint32_t sessId; 1114e57adabSTom Joseph // <Optional Field: AuthCode> 1124e57adabSTom Joseph uint8_t payloadLength; 1134e57adabSTom Joseph } __attribute__((packed)); 1144e57adabSTom Joseph 1154e57adabSTom Joseph struct SessionTrailer_t 1164e57adabSTom Joseph { 1174e57adabSTom Joseph uint8_t legacyPad; 1184e57adabSTom Joseph } __attribute__((packed)); 1194e57adabSTom Joseph 1203563f8feSTom Joseph /** 1214e57adabSTom Joseph * @brief Unflatten an incoming packet and prepare the IPMI message 1224e57adabSTom Joseph * 1234e57adabSTom Joseph * @param[in] inPacket - Incoming IPMI packet 1244e57adabSTom Joseph * 1254e57adabSTom Joseph * @return IPMI message in the packet on success 1264e57adabSTom Joseph */ 127d999ffc1SVernon Mauery std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket); 1284e57adabSTom Joseph 1293563f8feSTom Joseph /** 1304e57adabSTom Joseph * @brief Flatten an IPMI message and generate the IPMI packet with the 1314e57adabSTom Joseph * session header 1324e57adabSTom Joseph * 1334e57adabSTom Joseph * @param[in] outMessage - IPMI message to be flattened 1344e57adabSTom Joseph * 1354e57adabSTom Joseph * @return IPMI packet on success 1364e57adabSTom Joseph */ 137a82e4d3eSLei YU std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage, 138a82e4d3eSLei YU const std::shared_ptr<session::Session>& session); 1394e57adabSTom Joseph 1404e57adabSTom Joseph } // namespace ipmi15parser 1414e57adabSTom Joseph 1424e57adabSTom Joseph namespace ipmi20parser 1434e57adabSTom Joseph { 1444e57adabSTom Joseph 1454e57adabSTom Joseph constexpr size_t MAX_INTEGRITY_DATA_LENGTH = 12; 1464e57adabSTom Joseph constexpr size_t PAYLOAD_ENCRYPT_MASK = 0x80; 1474e57adabSTom Joseph constexpr size_t PAYLOAD_AUTH_MASK = 0x40; 1484e57adabSTom Joseph 1494e57adabSTom Joseph struct SessionHeader_t 1504e57adabSTom Joseph { 1514e57adabSTom Joseph struct parser::BasicHeader_t base; 1524e57adabSTom Joseph 1534e57adabSTom Joseph uint8_t payloadType; 1544e57adabSTom Joseph 1554e57adabSTom Joseph uint32_t sessId; 1564e57adabSTom Joseph uint32_t sessSeqNum; 1574e57adabSTom Joseph uint16_t payloadLength; 1584e57adabSTom Joseph } __attribute__((packed)); 1594e57adabSTom Joseph 1604e57adabSTom Joseph struct SessionTrailer_t 1614e57adabSTom Joseph { 1624e57adabSTom Joseph // Integrity Pad 1634e57adabSTom Joseph uint8_t padLength; 1644e57adabSTom Joseph uint8_t nextHeader; 1654e57adabSTom Joseph } __attribute__((packed)); 1664e57adabSTom Joseph 1673563f8feSTom Joseph /** 1684e57adabSTom Joseph * @brief Unflatten an incoming packet and prepare the IPMI message 1694e57adabSTom Joseph * 1704e57adabSTom Joseph * @param[in] inPacket - Incoming IPMI packet 1714e57adabSTom Joseph * 1724e57adabSTom Joseph * @return IPMI message in the packet on success 1734e57adabSTom Joseph */ 174d999ffc1SVernon Mauery std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket); 1754e57adabSTom Joseph 1763563f8feSTom Joseph /** 1774e57adabSTom Joseph * @brief Flatten an IPMI message and generate the IPMI packet with the 1784e57adabSTom Joseph * session header 1794e57adabSTom Joseph * 1804e57adabSTom Joseph * @param[in] outMessage - IPMI message to be flattened 181ce1f4fc5SLei YU * @param[in] session - session handle 1824e57adabSTom Joseph * 1834e57adabSTom Joseph * @return IPMI packet on success 1844e57adabSTom Joseph */ 185a82e4d3eSLei YU std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage, 186a82e4d3eSLei YU const std::shared_ptr<session::Session>& session); 1874e57adabSTom Joseph 1884e57adabSTom Joseph namespace internal 1894e57adabSTom Joseph { 1904e57adabSTom Joseph 1913563f8feSTom Joseph /** 1924e57adabSTom Joseph * @brief Add sequence number to the message 1934e57adabSTom Joseph * 1944e57adabSTom Joseph * @param[in] packet - outgoing packet to which to add sequence number 1954e57adabSTom Joseph * @param[in] session - session handle 1964e57adabSTom Joseph * 1974e57adabSTom Joseph */ 198224f36a4SVernon Mauery void addSequenceNumber(std::vector<uint8_t>& packet, 199a82e4d3eSLei YU const std::shared_ptr<session::Session>& session); 2004e57adabSTom Joseph 2013563f8feSTom Joseph /** 20264703f4dSTom Joseph * @brief Verify the integrity data of the incoming IPMI packet 20364703f4dSTom Joseph * 20464703f4dSTom Joseph * @param[in] packet - Incoming IPMI packet 205027dfc2cSTom Joseph * @param[in] message - IPMI Message populated from the incoming packet 206027dfc2cSTom Joseph * @param[in] payloadLen - Length of the IPMI payload 207ce1f4fc5SLei YU * @param[in] session - session handle 20864703f4dSTom Joseph * 20964703f4dSTom Joseph */ 21064703f4dSTom Joseph bool verifyPacketIntegrity(const std::vector<uint8_t>& packet, 211a82e4d3eSLei YU const std::shared_ptr<Message>& message, 212ce1f4fc5SLei YU size_t payloadLen, 213ce1f4fc5SLei YU const std::shared_ptr<session::Session>& session); 21464703f4dSTom Joseph 2153563f8feSTom Joseph /** 21664703f4dSTom Joseph * @brief Add Integrity data to the outgoing IPMI packet 21764703f4dSTom Joseph * 21864703f4dSTom Joseph * @param[in] packet - Outgoing IPMI packet 2191404bca6STom Joseph * @param[in] message - IPMI Message populated for the outgoing packet 2201404bca6STom Joseph * @param[in] payloadLen - Length of the IPMI payload 22164703f4dSTom Joseph */ 222d999ffc1SVernon Mauery void addIntegrityData(std::vector<uint8_t>& packet, 223a82e4d3eSLei YU const std::shared_ptr<Message>& message, 224a82e4d3eSLei YU size_t payloadLen, 225ce1f4fc5SLei YU const std::shared_ptr<session::Session>& session); 22664703f4dSTom Joseph 2273563f8feSTom Joseph /** 22878478a81STom Joseph * @brief Decrypt the encrypted payload in the incoming IPMI packet 22978478a81STom Joseph * 23078478a81STom Joseph * @param[in] packet - Incoming IPMI packet 23178478a81STom Joseph * @param[in] message - IPMI Message populated from the incoming packet 23278478a81STom Joseph * @param[in] payloadLen - Length of encrypted IPMI payload 233ce1f4fc5SLei YU * @param[in] session - session handle 23478478a81STom Joseph * 23578478a81STom Joseph * @return on successful completion, return the plain text payload 23678478a81STom Joseph */ 2378425624aSPatrick Williams std::vector<uint8_t> decryptPayload( 2388425624aSPatrick Williams const std::vector<uint8_t>& packet, const std::shared_ptr<Message>& message, 2398425624aSPatrick Williams size_t payloadLen, const std::shared_ptr<session::Session>& session); 24078478a81STom Joseph 2413563f8feSTom Joseph /** 24275362836STom Joseph * @brief Encrypt the plain text payload for the outgoing IPMI packet 24375362836STom Joseph * 24475362836STom Joseph * @param[in] message - IPMI Message populated for the outgoing packet 245ce1f4fc5SLei YU * @param[in] session - session handle 24675362836STom Joseph * 24775362836STom Joseph * @return on successful completion, return the encrypted payload 24875362836STom Joseph */ 249*33503e2aSPatrick Williams std::vector<uint8_t> encryptPayload( 250*33503e2aSPatrick Williams const std::shared_ptr<Message>& message, 251ce1f4fc5SLei YU const std::shared_ptr<session::Session>& session); 25275362836STom Joseph 2534e57adabSTom Joseph } // namespace internal 2544e57adabSTom Joseph 2554e57adabSTom Joseph } // namespace ipmi20parser 2564e57adabSTom Joseph 257de7dd5ceSKirill Pakhomov #ifdef RMCP_PING 258de7dd5ceSKirill Pakhomov namespace asfparser 259de7dd5ceSKirill Pakhomov { 260de7dd5ceSKirill Pakhomov 261de7dd5ceSKirill Pakhomov // ASF message fields for RMCP Ping message 262de7dd5ceSKirill Pakhomov struct AsfMessagePing_t 263de7dd5ceSKirill Pakhomov { 264de7dd5ceSKirill Pakhomov struct parser::RmcpHeader_t rmcp; 265de7dd5ceSKirill Pakhomov 266de7dd5ceSKirill Pakhomov uint32_t iana; 267de7dd5ceSKirill Pakhomov uint8_t msgType; 268de7dd5ceSKirill Pakhomov uint8_t msgTag; 269de7dd5ceSKirill Pakhomov uint8_t reserved; 270de7dd5ceSKirill Pakhomov uint8_t dataLen; 271de7dd5ceSKirill Pakhomov } __attribute__((packed)); 272de7dd5ceSKirill Pakhomov 273de7dd5ceSKirill Pakhomov // ASF message fields for RMCP Pong message 274de7dd5ceSKirill Pakhomov struct AsfMessagePong_t 275de7dd5ceSKirill Pakhomov { 276de7dd5ceSKirill Pakhomov struct AsfMessagePing_t ping; 277de7dd5ceSKirill Pakhomov 278de7dd5ceSKirill Pakhomov uint32_t iana; 279de7dd5ceSKirill Pakhomov uint32_t oemDefined; 280de7dd5ceSKirill Pakhomov uint8_t suppEntities; 281de7dd5ceSKirill Pakhomov uint8_t suppInteract; 282de7dd5ceSKirill Pakhomov uint32_t reserved1; 283de7dd5ceSKirill Pakhomov uint16_t reserved2; 284de7dd5ceSKirill Pakhomov } __attribute__((packed)); 285de7dd5ceSKirill Pakhomov 286de7dd5ceSKirill Pakhomov /** 287de7dd5ceSKirill Pakhomov * @brief Unflatten an incoming packet and prepare the ASF message 288de7dd5ceSKirill Pakhomov * 289de7dd5ceSKirill Pakhomov * @param[in] inPacket - Incoming ASF packet 290de7dd5ceSKirill Pakhomov * 291de7dd5ceSKirill Pakhomov * @return ASF message in the packet on success 292de7dd5ceSKirill Pakhomov */ 293de7dd5ceSKirill Pakhomov std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket); 294de7dd5ceSKirill Pakhomov 295de7dd5ceSKirill Pakhomov /** 296de7dd5ceSKirill Pakhomov * @brief Generate the ASF packet with the RMCP header 297de7dd5ceSKirill Pakhomov * 298de7dd5ceSKirill Pakhomov * @param[in] asfMsgTag - ASF Message Tag from Ping request 299de7dd5ceSKirill Pakhomov * 300de7dd5ceSKirill Pakhomov * @return ASF packet on success 301de7dd5ceSKirill Pakhomov */ 302de7dd5ceSKirill Pakhomov std::vector<uint8_t> flatten(uint8_t asfMsgTag); 303de7dd5ceSKirill Pakhomov 304de7dd5ceSKirill Pakhomov } // namespace asfparser 305de7dd5ceSKirill Pakhomov #endif // RMCP_PING 306de7dd5ceSKirill Pakhomov 3074e57adabSTom Joseph } // namespace message 308