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> unflatten(
63         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,
76                              SessionHeader authType,
77                              session::Session& session);
78 
79 } // namespace parser
80 
81 namespace ipmi15parser
82 {
83 
84 struct SessionHeader_t
85 {
86     struct parser::BasicHeader_t base;
87     uint32_t sessSeqNum;
88     uint32_t sessId;
89     // <Optional Field: AuthCode>
90     uint8_t payloadLength;
91 } __attribute__((packed));
92 
93 struct SessionTrailer_t
94 {
95     uint8_t legacyPad;
96 } __attribute__((packed));
97 
98 /**
99  * @brief Unflatten an incoming packet and prepare the IPMI message
100  *
101  * @param[in] inPacket - Incoming IPMI packet
102  *
103  * @return IPMI message in the packet on success
104  */
105 std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
106 
107 /**
108  * @brief Flatten an IPMI message and generate the IPMI packet with the
109  *        session header
110  *
111  * @param[in] outMessage - IPMI message to be flattened
112  *
113  * @return IPMI packet on success
114  */
115 std::vector<uint8_t> flatten(Message& outMessage, session::Session& session);
116 
117 } // namespace ipmi15parser
118 
119 namespace ipmi20parser
120 {
121 
122 constexpr size_t MAX_INTEGRITY_DATA_LENGTH = 12;
123 constexpr size_t PAYLOAD_ENCRYPT_MASK = 0x80;
124 constexpr size_t PAYLOAD_AUTH_MASK = 0x40;
125 
126 struct SessionHeader_t
127 {
128     struct parser::BasicHeader_t base;
129 
130     uint8_t payloadType;
131 
132     uint32_t sessId;
133     uint32_t sessSeqNum;
134     uint16_t payloadLength;
135 } __attribute__((packed));
136 
137 struct SessionTrailer_t
138 {
139     // Integrity Pad
140     uint8_t padLength;
141     uint8_t nextHeader;
142 } __attribute__((packed));
143 
144 /**
145  * @brief Unflatten an incoming packet and prepare the IPMI message
146  *
147  * @param[in] inPacket - Incoming IPMI packet
148  *
149  * @return IPMI message in the packet on success
150  */
151 std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
152 
153 /**
154  * @brief Flatten an IPMI message and generate the IPMI packet with the
155  *        session header
156  *
157  * @param[in] outMessage - IPMI message to be flattened
158  *
159  * @return IPMI packet on success
160  */
161 std::vector<uint8_t> flatten(Message& outMessage, session::Session& session);
162 
163 namespace internal
164 {
165 
166 /**
167  * @brief Add sequence number to the message
168  *
169  * @param[in] packet - outgoing packet to which to add sequence number
170  * @param[in] session - session handle
171  *
172  */
173 void addSequenceNumber(std::vector<uint8_t>& packet, session::Session& session);
174 
175 /**
176  * @brief Verify the integrity data of the incoming IPMI packet
177  *
178  * @param[in] packet - Incoming IPMI packet
179  * @param[in] message - IPMI Message populated from the incoming packet
180  * @param[in] payloadLen - Length of the IPMI payload
181  *
182  */
183 bool verifyPacketIntegrity(const std::vector<uint8_t>& packet,
184                            const Message& message,
185                            size_t payloadLen);
186 
187 /**
188  * @brief Add Integrity data to the outgoing IPMI packet
189  *
190  * @param[in] packet - Outgoing IPMI packet
191  * @param[in] message - IPMI Message populated for the outgoing packet
192  * @param[in] payloadLen - Length of the IPMI payload
193  */
194 void addIntegrityData(std::vector<uint8_t>& packet,
195                       const Message& message,
196                       size_t payloadLen);
197 
198 /**
199  * @brief Decrypt the encrypted payload in the incoming IPMI packet
200  *
201  * @param[in] packet - Incoming IPMI packet
202  * @param[in] message - IPMI Message populated from the incoming packet
203  * @param[in] payloadLen - Length of encrypted IPMI payload
204  *
205  * @return on successful completion, return the plain text payload
206  */
207 std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
208                                     const Message& message,
209                                     size_t payloadLen);
210 
211 /**
212  * @brief Encrypt the plain text payload for the outgoing IPMI packet
213  *
214  * @param[in] message - IPMI Message populated for the outgoing packet
215  *
216  * @return on successful completion, return the encrypted payload
217  */
218 std::vector<uint8_t> encryptPayload(Message& message);
219 
220 } // namespace internal
221 
222 } // namespace ipmi20parser
223 
224 } // namespace message
225