1 #pragma once
2 
3 #include "message.hpp"
4 #include "session.hpp"
5 
6 namespace message
7 {
8 
9 namespace parser
10 {
11 
12 constexpr size_t RMCP_VERSION = 6;
13 
14 // RMCP Messages with class=IPMI should be sent with an RMCP Sequence
15 // Number of FFh to indicate that an RMCP ACK message should not be
16 // generated by the message receiver.
17 constexpr size_t RMCP_SEQ = 0xFF;
18 
19 // RMCP Message Class 7h is for IPMI
20 constexpr size_t RMCP_MESSAGE_CLASS_IPMI = 7;
21 
22 // RMCP Session Header Size
23 constexpr size_t RMCP_SESSION_HEADER_SIZE = 4;
24 
25 // Maximum payload size
26 constexpr size_t MAX_PAYLOAD_SIZE = 255;
27 
28 enum class SessionHeader
29 {
30     IPMI15 = 0x00,
31     IPMI20 = 0x06,
32     INVALID = 0xFF,
33 };
34 
35 struct BasicHeader_t
36 {
37     // RMCP Header
38     uint8_t version;
39     uint8_t reserved;
40     uint8_t rmcpSeqNum;
41     uint8_t classOfMsg;
42 
43     // IPMI partial session header
44     union
45     {
46         uint8_t reserved1 : 4;
47         uint8_t authType : 4;
48         uint8_t formatType;
49     } format;
50 } __attribute__((packed));
51 
52 /**
53  * @brief Unflatten an incoming packet and prepare the IPMI message
54  *
55  * @param[in] inPacket - Incoming IPMI packet
56  *
57  * @return A tuple with IPMI message and the session header type to sent the
58  *         response packet. In case of success incoming message and session
59  *         header type. In case of failure nullptr and session header type
60  *         would be invalid.
61  */
62 std::tuple<std::unique_ptr<Message>, SessionHeader>
63     unflatten(std::vector<uint8_t>& inPacket);
64 
65 /**
66  * @brief Flatten an IPMI message and generate the IPMI packet with the
67  *        session header
68  *
69  * @param[in] outMessage - IPMI message to be flattened
70  * @param[in] authType - Session header type to be added to the IPMI
71  *                       packet
72  *
73  * @return IPMI packet on success
74  */
75 std::vector<uint8_t> flatten(Message& outMessage, SessionHeader authType,
76                              session::Session& session);
77 
78 } // namespace parser
79 
80 namespace ipmi15parser
81 {
82 
83 struct SessionHeader_t
84 {
85     struct parser::BasicHeader_t base;
86     uint32_t sessSeqNum;
87     uint32_t sessId;
88     // <Optional Field: AuthCode>
89     uint8_t payloadLength;
90 } __attribute__((packed));
91 
92 struct SessionTrailer_t
93 {
94     uint8_t legacyPad;
95 } __attribute__((packed));
96 
97 /**
98  * @brief Unflatten an incoming packet and prepare the IPMI message
99  *
100  * @param[in] inPacket - Incoming IPMI packet
101  *
102  * @return IPMI message in the packet on success
103  */
104 std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
105 
106 /**
107  * @brief Flatten an IPMI message and generate the IPMI packet with the
108  *        session header
109  *
110  * @param[in] outMessage - IPMI message to be flattened
111  *
112  * @return IPMI packet on success
113  */
114 std::vector<uint8_t> flatten(Message& outMessage, session::Session& session);
115 
116 } // namespace ipmi15parser
117 
118 namespace ipmi20parser
119 {
120 
121 constexpr size_t MAX_INTEGRITY_DATA_LENGTH = 12;
122 constexpr size_t PAYLOAD_ENCRYPT_MASK = 0x80;
123 constexpr size_t PAYLOAD_AUTH_MASK = 0x40;
124 
125 struct SessionHeader_t
126 {
127     struct parser::BasicHeader_t base;
128 
129     uint8_t payloadType;
130 
131     uint32_t sessId;
132     uint32_t sessSeqNum;
133     uint16_t payloadLength;
134 } __attribute__((packed));
135 
136 struct SessionTrailer_t
137 {
138     // Integrity Pad
139     uint8_t padLength;
140     uint8_t nextHeader;
141 } __attribute__((packed));
142 
143 /**
144  * @brief Unflatten an incoming packet and prepare the IPMI message
145  *
146  * @param[in] inPacket - Incoming IPMI packet
147  *
148  * @return IPMI message in the packet on success
149  */
150 std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
151 
152 /**
153  * @brief Flatten an IPMI message and generate the IPMI packet with the
154  *        session header
155  *
156  * @param[in] outMessage - IPMI message to be flattened
157  *
158  * @return IPMI packet on success
159  */
160 std::vector<uint8_t> flatten(Message& outMessage, session::Session& session);
161 
162 namespace internal
163 {
164 
165 /**
166  * @brief Add sequence number to the message
167  *
168  * @param[in] packet - outgoing packet to which to add sequence number
169  * @param[in] session - session handle
170  *
171  */
172 void addSequenceNumber(std::vector<uint8_t>& packet, session::Session& session);
173 
174 /**
175  * @brief Verify the integrity data of the incoming IPMI packet
176  *
177  * @param[in] packet - Incoming IPMI packet
178  * @param[in] message - IPMI Message populated from the incoming packet
179  * @param[in] payloadLen - Length of the IPMI payload
180  *
181  */
182 bool verifyPacketIntegrity(const std::vector<uint8_t>& packet,
183                            const Message& message, size_t payloadLen);
184 
185 /**
186  * @brief Add Integrity data to the outgoing IPMI packet
187  *
188  * @param[in] packet - Outgoing IPMI packet
189  * @param[in] message - IPMI Message populated for the outgoing packet
190  * @param[in] payloadLen - Length of the IPMI payload
191  */
192 void addIntegrityData(std::vector<uint8_t>& packet, const Message& message,
193                       size_t payloadLen);
194 
195 /**
196  * @brief Decrypt the encrypted payload in the incoming IPMI packet
197  *
198  * @param[in] packet - Incoming IPMI packet
199  * @param[in] message - IPMI Message populated from the incoming packet
200  * @param[in] payloadLen - Length of encrypted IPMI payload
201  *
202  * @return on successful completion, return the plain text payload
203  */
204 std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
205                                     const Message& message, size_t payloadLen);
206 
207 /**
208  * @brief Encrypt the plain text payload for the outgoing IPMI packet
209  *
210  * @param[in] message - IPMI Message populated for the outgoing packet
211  *
212  * @return on successful completion, return the encrypted payload
213  */
214 std::vector<uint8_t> encryptPayload(Message& message);
215 
216 } // namespace internal
217 
218 } // namespace ipmi20parser
219 
220 } // namespace message
221