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  */
84d999ffc1SVernon Mauery std::tuple<std::shared_ptr<Message>, SessionHeader>
859e801a2bSVernon Mauery     unflatten(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  */
97*a82e4d3eSLei YU std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage,
98224f36a4SVernon Mauery                              SessionHeader authType,
99*a82e4d3eSLei 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  */
137*a82e4d3eSLei YU std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage,
138*a82e4d3eSLei 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  */
185*a82e4d3eSLei YU std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage,
186*a82e4d3eSLei 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,
199*a82e4d3eSLei 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,
211*a82e4d3eSLei 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,
223*a82e4d3eSLei YU                       const std::shared_ptr<Message>& message,
224*a82e4d3eSLei 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  */
237ce1f4fc5SLei YU std::vector<uint8_t>
238ce1f4fc5SLei YU     decryptPayload(const std::vector<uint8_t>& packet,
239*a82e4d3eSLei YU                    const std::shared_ptr<Message>& message, size_t payloadLen,
240ce1f4fc5SLei YU                    const std::shared_ptr<session::Session>& session);
24178478a81STom Joseph 
2423563f8feSTom Joseph /**
24375362836STom Joseph  * @brief Encrypt the plain text payload for the outgoing IPMI packet
24475362836STom Joseph  *
24575362836STom Joseph  * @param[in] message - IPMI Message populated for the outgoing packet
246ce1f4fc5SLei YU  * @param[in] session - session handle
24775362836STom Joseph  *
24875362836STom Joseph  * @return on successful completion, return the encrypted payload
24975362836STom Joseph  */
250ce1f4fc5SLei YU std::vector<uint8_t>
251*a82e4d3eSLei YU     encryptPayload(const std::shared_ptr<Message>& message,
252ce1f4fc5SLei YU                    const std::shared_ptr<session::Session>& session);
25375362836STom Joseph 
2544e57adabSTom Joseph } // namespace internal
2554e57adabSTom Joseph 
2564e57adabSTom Joseph } // namespace ipmi20parser
2574e57adabSTom Joseph 
258de7dd5ceSKirill Pakhomov #ifdef RMCP_PING
259de7dd5ceSKirill Pakhomov namespace asfparser
260de7dd5ceSKirill Pakhomov {
261de7dd5ceSKirill Pakhomov 
262de7dd5ceSKirill Pakhomov // ASF message fields for RMCP Ping message
263de7dd5ceSKirill Pakhomov struct AsfMessagePing_t
264de7dd5ceSKirill Pakhomov {
265de7dd5ceSKirill Pakhomov     struct parser::RmcpHeader_t rmcp;
266de7dd5ceSKirill Pakhomov 
267de7dd5ceSKirill Pakhomov     uint32_t iana;
268de7dd5ceSKirill Pakhomov     uint8_t msgType;
269de7dd5ceSKirill Pakhomov     uint8_t msgTag;
270de7dd5ceSKirill Pakhomov     uint8_t reserved;
271de7dd5ceSKirill Pakhomov     uint8_t dataLen;
272de7dd5ceSKirill Pakhomov } __attribute__((packed));
273de7dd5ceSKirill Pakhomov 
274de7dd5ceSKirill Pakhomov // ASF message fields for RMCP Pong message
275de7dd5ceSKirill Pakhomov struct AsfMessagePong_t
276de7dd5ceSKirill Pakhomov {
277de7dd5ceSKirill Pakhomov     struct AsfMessagePing_t ping;
278de7dd5ceSKirill Pakhomov 
279de7dd5ceSKirill Pakhomov     uint32_t iana;
280de7dd5ceSKirill Pakhomov     uint32_t oemDefined;
281de7dd5ceSKirill Pakhomov     uint8_t suppEntities;
282de7dd5ceSKirill Pakhomov     uint8_t suppInteract;
283de7dd5ceSKirill Pakhomov     uint32_t reserved1;
284de7dd5ceSKirill Pakhomov     uint16_t reserved2;
285de7dd5ceSKirill Pakhomov } __attribute__((packed));
286de7dd5ceSKirill Pakhomov 
287de7dd5ceSKirill Pakhomov /**
288de7dd5ceSKirill Pakhomov  * @brief Unflatten an incoming packet and prepare the ASF message
289de7dd5ceSKirill Pakhomov  *
290de7dd5ceSKirill Pakhomov  * @param[in] inPacket - Incoming ASF packet
291de7dd5ceSKirill Pakhomov  *
292de7dd5ceSKirill Pakhomov  * @return ASF message in the packet on success
293de7dd5ceSKirill Pakhomov  */
294de7dd5ceSKirill Pakhomov std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
295de7dd5ceSKirill Pakhomov 
296de7dd5ceSKirill Pakhomov /**
297de7dd5ceSKirill Pakhomov  * @brief Generate the ASF packet with the RMCP header
298de7dd5ceSKirill Pakhomov  *
299de7dd5ceSKirill Pakhomov  * @param[in] asfMsgTag - ASF Message Tag from Ping request
300de7dd5ceSKirill Pakhomov  *
301de7dd5ceSKirill Pakhomov  * @return ASF packet on success
302de7dd5ceSKirill Pakhomov  */
303de7dd5ceSKirill Pakhomov std::vector<uint8_t> flatten(uint8_t asfMsgTag);
304de7dd5ceSKirill Pakhomov 
305de7dd5ceSKirill Pakhomov } // namespace asfparser
306de7dd5ceSKirill Pakhomov #endif // RMCP_PING
307de7dd5ceSKirill Pakhomov 
3084e57adabSTom Joseph } // namespace message
309