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 
524e57adabSTom 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 
654e57adabSTom 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 
984e57adabSTom 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 
1074e57adabSTom 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 
1444e57adabSTom 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 
1534e57adabSTom 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 
1664e57adabSTom 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 
17564703f4dSTom 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 
18764703f4dSTom 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 
19878478a81STom 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*75362836STom Joseph /*
212*75362836STom Joseph  * @brief Encrypt the plain text payload for the outgoing IPMI packet
213*75362836STom Joseph  *
214*75362836STom Joseph  * @param[in] message - IPMI Message populated for the outgoing packet
215*75362836STom Joseph  *
216*75362836STom Joseph  * @return on successful completion, return the encrypted payload
217*75362836STom Joseph  */
218*75362836STom Joseph std::vector<uint8_t> encryptPayload(Message& message);
219*75362836STom Joseph 
2204e57adabSTom Joseph } // namespace internal
2214e57adabSTom Joseph 
2224e57adabSTom Joseph } // namespace ipmi20parser
2234e57adabSTom Joseph 
2244e57adabSTom Joseph } // namespace message
225