14e57adabSTom Joseph #pragma once 24e57adabSTom Joseph 34e57adabSTom Joseph #include "message.hpp" 44e57adabSTom Joseph #include "session.hpp" 54e57adabSTom Joseph 64e57adabSTom Joseph namespace message 74e57adabSTom Joseph { 84e57adabSTom Joseph 94e57adabSTom Joseph namespace parser 104e57adabSTom Joseph { 114e57adabSTom Joseph 124e57adabSTom Joseph constexpr size_t RMCP_VERSION = 6; 134e57adabSTom Joseph 144e57adabSTom Joseph // RMCP Messages with class=IPMI should be sent with an RMCP Sequence 154e57adabSTom Joseph // Number of FFh to indicate that an RMCP ACK message should not be 164e57adabSTom Joseph // generated by the message receiver. 174e57adabSTom Joseph constexpr size_t RMCP_SEQ = 0xFF; 184e57adabSTom Joseph 194e57adabSTom Joseph // RMCP Message Class 7h is for IPMI 204e57adabSTom Joseph constexpr size_t RMCP_MESSAGE_CLASS_IPMI = 7; 214e57adabSTom Joseph 2264703f4dSTom Joseph // RMCP Session Header Size 2364703f4dSTom Joseph constexpr size_t RMCP_SESSION_HEADER_SIZE = 4; 2464703f4dSTom Joseph 251efcb493STom Joseph // Maximum payload size 261efcb493STom Joseph constexpr size_t MAX_PAYLOAD_SIZE = 255; 271efcb493STom Joseph 284e57adabSTom Joseph enum class SessionHeader 294e57adabSTom Joseph { 304e57adabSTom Joseph IPMI15 = 0x00, 314e57adabSTom Joseph IPMI20 = 0x06, 324e57adabSTom Joseph INVALID = 0xFF, 334e57adabSTom Joseph }; 344e57adabSTom Joseph 354e57adabSTom Joseph struct BasicHeader_t 364e57adabSTom Joseph { 374e57adabSTom Joseph // RMCP Header 384e57adabSTom Joseph uint8_t version; 394e57adabSTom Joseph uint8_t reserved; 404e57adabSTom Joseph uint8_t rmcpSeqNum; 414e57adabSTom Joseph uint8_t classOfMsg; 424e57adabSTom Joseph 434e57adabSTom Joseph // IPMI partial session header 444e57adabSTom Joseph union 454e57adabSTom Joseph { 464e57adabSTom Joseph uint8_t reserved1: 4; 474e57adabSTom Joseph uint8_t authType: 4; 484e57adabSTom Joseph uint8_t formatType; 494e57adabSTom Joseph } format; 504e57adabSTom Joseph } __attribute__((packed)); 514e57adabSTom Joseph 52*3563f8feSTom Joseph /** 534e57adabSTom Joseph * @brief Unflatten an incoming packet and prepare the IPMI message 544e57adabSTom Joseph * 554e57adabSTom Joseph * @param[in] inPacket - Incoming IPMI packet 564e57adabSTom Joseph * 574e57adabSTom Joseph * @return A tuple with IPMI message and the session header type to sent the 584e57adabSTom Joseph * response packet. In case of success incoming message and session 594e57adabSTom Joseph * header type. In case of failure nullptr and session header type 604e57adabSTom Joseph * would be invalid. 614e57adabSTom Joseph */ 624e57adabSTom Joseph std::tuple<std::unique_ptr<Message>, SessionHeader> unflatten( 634e57adabSTom Joseph std::vector<uint8_t>& inPacket); 644e57adabSTom Joseph 65*3563f8feSTom Joseph /** 664e57adabSTom Joseph * @brief Flatten an IPMI message and generate the IPMI packet with the 674e57adabSTom Joseph * session header 684e57adabSTom Joseph * 694e57adabSTom Joseph * @param[in] outMessage - IPMI message to be flattened 704e57adabSTom Joseph * @param[in] authType - Session header type to be added to the IPMI 714e57adabSTom Joseph * packet 724e57adabSTom Joseph * 734e57adabSTom Joseph * @return IPMI packet on success 744e57adabSTom Joseph */ 754e57adabSTom Joseph std::vector<uint8_t> flatten(Message& outMessage, 764e57adabSTom Joseph SessionHeader authType, 774e57adabSTom Joseph session::Session& session); 784e57adabSTom Joseph 794e57adabSTom Joseph } // namespace parser 804e57adabSTom Joseph 814e57adabSTom Joseph namespace ipmi15parser 824e57adabSTom Joseph { 834e57adabSTom Joseph 844e57adabSTom Joseph struct SessionHeader_t 854e57adabSTom Joseph { 864e57adabSTom Joseph struct parser::BasicHeader_t base; 874e57adabSTom Joseph uint32_t sessSeqNum; 884e57adabSTom Joseph uint32_t sessId; 894e57adabSTom Joseph // <Optional Field: AuthCode> 904e57adabSTom Joseph uint8_t payloadLength; 914e57adabSTom Joseph } __attribute__((packed)); 924e57adabSTom Joseph 934e57adabSTom Joseph struct SessionTrailer_t 944e57adabSTom Joseph { 954e57adabSTom Joseph uint8_t legacyPad; 964e57adabSTom Joseph } __attribute__((packed)); 974e57adabSTom Joseph 98*3563f8feSTom Joseph /** 994e57adabSTom Joseph * @brief Unflatten an incoming packet and prepare the IPMI message 1004e57adabSTom Joseph * 1014e57adabSTom Joseph * @param[in] inPacket - Incoming IPMI packet 1024e57adabSTom Joseph * 1034e57adabSTom Joseph * @return IPMI message in the packet on success 1044e57adabSTom Joseph */ 1054e57adabSTom Joseph std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket); 1064e57adabSTom Joseph 107*3563f8feSTom Joseph /** 1084e57adabSTom Joseph * @brief Flatten an IPMI message and generate the IPMI packet with the 1094e57adabSTom Joseph * session header 1104e57adabSTom Joseph * 1114e57adabSTom Joseph * @param[in] outMessage - IPMI message to be flattened 1124e57adabSTom Joseph * 1134e57adabSTom Joseph * @return IPMI packet on success 1144e57adabSTom Joseph */ 1154e57adabSTom Joseph std::vector<uint8_t> flatten(Message& outMessage, session::Session& session); 1164e57adabSTom Joseph 1174e57adabSTom Joseph } // namespace ipmi15parser 1184e57adabSTom Joseph 1194e57adabSTom Joseph namespace ipmi20parser 1204e57adabSTom Joseph { 1214e57adabSTom Joseph 1224e57adabSTom Joseph constexpr size_t MAX_INTEGRITY_DATA_LENGTH = 12; 1234e57adabSTom Joseph constexpr size_t PAYLOAD_ENCRYPT_MASK = 0x80; 1244e57adabSTom Joseph constexpr size_t PAYLOAD_AUTH_MASK = 0x40; 1254e57adabSTom Joseph 1264e57adabSTom Joseph struct SessionHeader_t 1274e57adabSTom Joseph { 1284e57adabSTom Joseph struct parser::BasicHeader_t base; 1294e57adabSTom Joseph 1304e57adabSTom Joseph uint8_t payloadType; 1314e57adabSTom Joseph 1324e57adabSTom Joseph uint32_t sessId; 1334e57adabSTom Joseph uint32_t sessSeqNum; 1344e57adabSTom Joseph uint16_t payloadLength; 1354e57adabSTom Joseph } __attribute__((packed)); 1364e57adabSTom Joseph 1374e57adabSTom Joseph struct SessionTrailer_t 1384e57adabSTom Joseph { 1394e57adabSTom Joseph // Integrity Pad 1404e57adabSTom Joseph uint8_t padLength; 1414e57adabSTom Joseph uint8_t nextHeader; 1424e57adabSTom Joseph } __attribute__((packed)); 1434e57adabSTom Joseph 144*3563f8feSTom Joseph /** 1454e57adabSTom Joseph * @brief Unflatten an incoming packet and prepare the IPMI message 1464e57adabSTom Joseph * 1474e57adabSTom Joseph * @param[in] inPacket - Incoming IPMI packet 1484e57adabSTom Joseph * 1494e57adabSTom Joseph * @return IPMI message in the packet on success 1504e57adabSTom Joseph */ 1514e57adabSTom Joseph std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket); 1524e57adabSTom Joseph 153*3563f8feSTom Joseph /** 1544e57adabSTom Joseph * @brief Flatten an IPMI message and generate the IPMI packet with the 1554e57adabSTom Joseph * session header 1564e57adabSTom Joseph * 1574e57adabSTom Joseph * @param[in] outMessage - IPMI message to be flattened 1584e57adabSTom Joseph * 1594e57adabSTom Joseph * @return IPMI packet on success 1604e57adabSTom Joseph */ 1614e57adabSTom Joseph std::vector<uint8_t> flatten(Message& outMessage, session::Session& session); 1624e57adabSTom Joseph 1634e57adabSTom Joseph namespace internal 1644e57adabSTom Joseph { 1654e57adabSTom Joseph 166*3563f8feSTom Joseph /** 1674e57adabSTom Joseph * @brief Add sequence number to the message 1684e57adabSTom Joseph * 1694e57adabSTom Joseph * @param[in] packet - outgoing packet to which to add sequence number 1704e57adabSTom Joseph * @param[in] session - session handle 1714e57adabSTom Joseph * 1724e57adabSTom Joseph */ 1734e57adabSTom Joseph void addSequenceNumber(std::vector<uint8_t>& packet, session::Session& session); 1744e57adabSTom Joseph 175*3563f8feSTom Joseph /** 17664703f4dSTom Joseph * @brief Verify the integrity data of the incoming IPMI packet 17764703f4dSTom Joseph * 17864703f4dSTom Joseph * @param[in] packet - Incoming IPMI packet 179027dfc2cSTom Joseph * @param[in] message - IPMI Message populated from the incoming packet 180027dfc2cSTom Joseph * @param[in] payloadLen - Length of the IPMI payload 18164703f4dSTom Joseph * 18264703f4dSTom Joseph */ 18364703f4dSTom Joseph bool verifyPacketIntegrity(const std::vector<uint8_t>& packet, 184027dfc2cSTom Joseph const Message& message, 185027dfc2cSTom Joseph size_t payloadLen); 18664703f4dSTom Joseph 187*3563f8feSTom Joseph /** 18864703f4dSTom Joseph * @brief Add Integrity data to the outgoing IPMI packet 18964703f4dSTom Joseph * 19064703f4dSTom Joseph * @param[in] packet - Outgoing IPMI packet 1911404bca6STom Joseph * @param[in] message - IPMI Message populated for the outgoing packet 1921404bca6STom Joseph * @param[in] payloadLen - Length of the IPMI payload 19364703f4dSTom Joseph */ 1941404bca6STom Joseph void addIntegrityData(std::vector<uint8_t>& packet, 1951404bca6STom Joseph const Message& message, 1961404bca6STom Joseph size_t payloadLen); 19764703f4dSTom Joseph 198*3563f8feSTom Joseph /** 19978478a81STom Joseph * @brief Decrypt the encrypted payload in the incoming IPMI packet 20078478a81STom Joseph * 20178478a81STom Joseph * @param[in] packet - Incoming IPMI packet 20278478a81STom Joseph * @param[in] message - IPMI Message populated from the incoming packet 20378478a81STom Joseph * @param[in] payloadLen - Length of encrypted IPMI payload 20478478a81STom Joseph * 20578478a81STom Joseph * @return on successful completion, return the plain text payload 20678478a81STom Joseph */ 20778478a81STom Joseph std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet, 20878478a81STom Joseph const Message& message, 20978478a81STom Joseph size_t payloadLen); 21078478a81STom Joseph 211*3563f8feSTom Joseph /** 21275362836STom Joseph * @brief Encrypt the plain text payload for the outgoing IPMI packet 21375362836STom Joseph * 21475362836STom Joseph * @param[in] message - IPMI Message populated for the outgoing packet 21575362836STom Joseph * 21675362836STom Joseph * @return on successful completion, return the encrypted payload 21775362836STom Joseph */ 21875362836STom Joseph std::vector<uint8_t> encryptPayload(Message& message); 21975362836STom Joseph 2204e57adabSTom Joseph } // namespace internal 2214e57adabSTom Joseph 2224e57adabSTom Joseph } // namespace ipmi20parser 2234e57adabSTom Joseph 2244e57adabSTom Joseph } // namespace message 225