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 
523563f8feSTom 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  */
62*d999ffc1SVernon Mauery std::tuple<std::shared_ptr<Message>, SessionHeader>
639e801a2bSVernon Mauery     unflatten(std::vector<uint8_t>& inPacket);
644e57adabSTom Joseph 
653563f8feSTom 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  */
75*d999ffc1SVernon Mauery std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
76*d999ffc1SVernon Mauery                              SessionHeader authType, session::Session& session);
774e57adabSTom Joseph 
784e57adabSTom Joseph } // namespace parser
794e57adabSTom Joseph 
804e57adabSTom Joseph namespace ipmi15parser
814e57adabSTom Joseph {
824e57adabSTom Joseph 
834e57adabSTom Joseph struct SessionHeader_t
844e57adabSTom Joseph {
854e57adabSTom Joseph     struct parser::BasicHeader_t base;
864e57adabSTom Joseph     uint32_t sessSeqNum;
874e57adabSTom Joseph     uint32_t sessId;
884e57adabSTom Joseph     // <Optional Field: AuthCode>
894e57adabSTom Joseph     uint8_t payloadLength;
904e57adabSTom Joseph } __attribute__((packed));
914e57adabSTom Joseph 
924e57adabSTom Joseph struct SessionTrailer_t
934e57adabSTom Joseph {
944e57adabSTom Joseph     uint8_t legacyPad;
954e57adabSTom Joseph } __attribute__((packed));
964e57adabSTom Joseph 
973563f8feSTom Joseph /**
984e57adabSTom Joseph  * @brief Unflatten an incoming packet and prepare the IPMI message
994e57adabSTom Joseph  *
1004e57adabSTom Joseph  * @param[in] inPacket - Incoming IPMI packet
1014e57adabSTom Joseph  *
1024e57adabSTom Joseph  * @return IPMI message in the packet on success
1034e57adabSTom Joseph  */
104*d999ffc1SVernon Mauery std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
1054e57adabSTom Joseph 
1063563f8feSTom Joseph /**
1074e57adabSTom Joseph  * @brief Flatten an IPMI message and generate the IPMI packet with the
1084e57adabSTom Joseph  *        session header
1094e57adabSTom Joseph  *
1104e57adabSTom Joseph  * @param[in] outMessage - IPMI message to be flattened
1114e57adabSTom Joseph  *
1124e57adabSTom Joseph  * @return IPMI packet on success
1134e57adabSTom Joseph  */
114*d999ffc1SVernon Mauery std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
115*d999ffc1SVernon Mauery                              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 
1443563f8feSTom 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  */
151*d999ffc1SVernon Mauery std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
1524e57adabSTom Joseph 
1533563f8feSTom 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  */
161*d999ffc1SVernon Mauery std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
162*d999ffc1SVernon Mauery                              session::Session& session);
1634e57adabSTom Joseph 
1644e57adabSTom Joseph namespace internal
1654e57adabSTom Joseph {
1664e57adabSTom Joseph 
1673563f8feSTom Joseph /**
1684e57adabSTom Joseph  * @brief Add sequence number to the message
1694e57adabSTom Joseph  *
1704e57adabSTom Joseph  * @param[in] packet - outgoing packet to which to add sequence number
1714e57adabSTom Joseph  * @param[in] session - session handle
1724e57adabSTom Joseph  *
1734e57adabSTom Joseph  */
1744e57adabSTom Joseph void addSequenceNumber(std::vector<uint8_t>& packet, session::Session& session);
1754e57adabSTom Joseph 
1763563f8feSTom Joseph /**
17764703f4dSTom Joseph  * @brief Verify the integrity data of the incoming IPMI packet
17864703f4dSTom Joseph  *
17964703f4dSTom Joseph  * @param[in] packet - Incoming IPMI packet
180027dfc2cSTom Joseph  * @param[in] message - IPMI Message populated from the incoming packet
181027dfc2cSTom Joseph  * @param[in] payloadLen - Length of the IPMI payload
18264703f4dSTom Joseph  *
18364703f4dSTom Joseph  */
18464703f4dSTom Joseph bool verifyPacketIntegrity(const std::vector<uint8_t>& packet,
185*d999ffc1SVernon Mauery                            const std::shared_ptr<Message> message,
186*d999ffc1SVernon Mauery                            size_t payloadLen);
18764703f4dSTom Joseph 
1883563f8feSTom Joseph /**
18964703f4dSTom Joseph  * @brief Add Integrity data to the outgoing IPMI packet
19064703f4dSTom Joseph  *
19164703f4dSTom Joseph  * @param[in] packet - Outgoing IPMI packet
1921404bca6STom Joseph  * @param[in] message - IPMI Message populated for the outgoing packet
1931404bca6STom Joseph  * @param[in] payloadLen - Length of the IPMI payload
19464703f4dSTom Joseph  */
195*d999ffc1SVernon Mauery void addIntegrityData(std::vector<uint8_t>& packet,
196*d999ffc1SVernon Mauery                       const std::shared_ptr<Message> message,
1971404bca6STom Joseph                       size_t payloadLen);
19864703f4dSTom Joseph 
1993563f8feSTom Joseph /**
20078478a81STom Joseph  * @brief Decrypt the encrypted payload in the incoming IPMI packet
20178478a81STom Joseph  *
20278478a81STom Joseph  * @param[in] packet - Incoming IPMI packet
20378478a81STom Joseph  * @param[in] message - IPMI Message populated from the incoming packet
20478478a81STom Joseph  * @param[in] payloadLen - Length of encrypted IPMI payload
20578478a81STom Joseph  *
20678478a81STom Joseph  * @return on successful completion, return the plain text payload
20778478a81STom Joseph  */
20878478a81STom Joseph std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
209*d999ffc1SVernon Mauery                                     const std::shared_ptr<Message> message,
210*d999ffc1SVernon Mauery                                     size_t payloadLen);
21178478a81STom Joseph 
2123563f8feSTom Joseph /**
21375362836STom Joseph  * @brief Encrypt the plain text payload for the outgoing IPMI packet
21475362836STom Joseph  *
21575362836STom Joseph  * @param[in] message - IPMI Message populated for the outgoing packet
21675362836STom Joseph  *
21775362836STom Joseph  * @return on successful completion, return the encrypted payload
21875362836STom Joseph  */
219*d999ffc1SVernon Mauery std::vector<uint8_t> encryptPayload(std::shared_ptr<Message> message);
22075362836STom Joseph 
2214e57adabSTom Joseph } // namespace internal
2224e57adabSTom Joseph 
2234e57adabSTom Joseph } // namespace ipmi20parser
2244e57adabSTom Joseph 
2254e57adabSTom Joseph } // namespace message
226