1 #pragma once 2 3 #include "message.hpp" 4 #include "session.hpp" 5 6 #include <cstddef> 7 8 namespace message 9 { 10 11 namespace parser 12 { 13 14 constexpr size_t RMCP_VERSION = 6; 15 16 // RMCP Messages with class=IPMI should be sent with an RMCP Sequence 17 // Number of FFh to indicate that an RMCP ACK message should not be 18 // generated by the message receiver. 19 constexpr size_t RMCP_SEQ = 0xFF; 20 21 // RMCP Message Class 7h is for IPMI 22 constexpr size_t RMCP_MESSAGE_CLASS_IPMI = 7; 23 24 // RMCP Session Header Size 25 constexpr size_t RMCP_SESSION_HEADER_SIZE = 4; 26 27 // RMCP/ASF Pong Message ASF Header Data Length 28 // as per IPMI spec 13.2.4 29 constexpr size_t RMCP_ASF_PONG_DATA_LEN = 16; 30 31 // ASF IANA 32 constexpr uint32_t ASF_IANA = 4542; 33 34 // ASF Supported Entities 35 constexpr uint32_t ASF_SUPP_ENT = 0x81; 36 37 // ASF Supported Entities 38 constexpr uint32_t ASF_SUPP_INT = 0x00; 39 40 // Maximum payload size 41 constexpr size_t MAX_PAYLOAD_SIZE = 255; 42 43 enum class SessionHeader 44 { 45 IPMI15 = 0x00, 46 IPMI20 = 0x06, 47 INVALID = 0xFF, 48 }; 49 50 // RMCP Header 51 struct RmcpHeader_t 52 { 53 // RMCP Header 54 uint8_t version; 55 uint8_t reserved; 56 uint8_t rmcpSeqNum; 57 uint8_t classOfMsg; 58 } __attribute__((packed)); 59 60 struct BasicHeader_t 61 { 62 // RMCP Header 63 struct RmcpHeader_t rmcp; 64 65 // IPMI partial session header 66 union 67 { 68 uint8_t reserved1 : 4; 69 uint8_t authType : 4; 70 uint8_t formatType; 71 } format; 72 } __attribute__((packed)); 73 74 /** 75 * @brief Unflatten an incoming packet and prepare the IPMI message 76 * 77 * @param[in] inPacket - Incoming IPMI packet 78 * 79 * @return A tuple with IPMI message and the session header type to sent the 80 * response packet. In case of success incoming message and session 81 * header type. In case of failure nullptr and session header type 82 * would be invalid. 83 */ 84 std::tuple<std::shared_ptr<Message>, SessionHeader> 85 unflatten(std::vector<uint8_t>& inPacket); 86 87 /** 88 * @brief Flatten an IPMI message and generate the IPMI packet with the 89 * session header 90 * 91 * @param[in] outMessage - IPMI message to be flattened 92 * @param[in] authType - Session header type to be added to the IPMI 93 * packet 94 * 95 * @return IPMI packet on success 96 */ 97 std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage, 98 SessionHeader authType, 99 const std::shared_ptr<session::Session>& session); 100 101 } // namespace parser 102 103 namespace ipmi15parser 104 { 105 106 struct SessionHeader_t 107 { 108 struct parser::BasicHeader_t base; 109 uint32_t sessSeqNum; 110 uint32_t sessId; 111 // <Optional Field: AuthCode> 112 uint8_t payloadLength; 113 } __attribute__((packed)); 114 115 struct SessionTrailer_t 116 { 117 uint8_t legacyPad; 118 } __attribute__((packed)); 119 120 /** 121 * @brief Unflatten an incoming packet and prepare the IPMI message 122 * 123 * @param[in] inPacket - Incoming IPMI packet 124 * 125 * @return IPMI message in the packet on success 126 */ 127 std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket); 128 129 /** 130 * @brief Flatten an IPMI message and generate the IPMI packet with the 131 * session header 132 * 133 * @param[in] outMessage - IPMI message to be flattened 134 * 135 * @return IPMI packet on success 136 */ 137 std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage, 138 const std::shared_ptr<session::Session>& session); 139 140 } // namespace ipmi15parser 141 142 namespace ipmi20parser 143 { 144 145 constexpr size_t MAX_INTEGRITY_DATA_LENGTH = 12; 146 constexpr size_t PAYLOAD_ENCRYPT_MASK = 0x80; 147 constexpr size_t PAYLOAD_AUTH_MASK = 0x40; 148 149 struct SessionHeader_t 150 { 151 struct parser::BasicHeader_t base; 152 153 uint8_t payloadType; 154 155 uint32_t sessId; 156 uint32_t sessSeqNum; 157 uint16_t payloadLength; 158 } __attribute__((packed)); 159 160 struct SessionTrailer_t 161 { 162 // Integrity Pad 163 uint8_t padLength; 164 uint8_t nextHeader; 165 } __attribute__((packed)); 166 167 /** 168 * @brief Unflatten an incoming packet and prepare the IPMI message 169 * 170 * @param[in] inPacket - Incoming IPMI packet 171 * 172 * @return IPMI message in the packet on success 173 */ 174 std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket); 175 176 /** 177 * @brief Flatten an IPMI message and generate the IPMI packet with the 178 * session header 179 * 180 * @param[in] outMessage - IPMI message to be flattened 181 * @param[in] session - session handle 182 * 183 * @return IPMI packet on success 184 */ 185 std::vector<uint8_t> flatten(const std::shared_ptr<Message>& outMessage, 186 const std::shared_ptr<session::Session>& session); 187 188 namespace internal 189 { 190 191 /** 192 * @brief Add sequence number to the message 193 * 194 * @param[in] packet - outgoing packet to which to add sequence number 195 * @param[in] session - session handle 196 * 197 */ 198 void addSequenceNumber(std::vector<uint8_t>& packet, 199 const std::shared_ptr<session::Session>& session); 200 201 /** 202 * @brief Verify the integrity data of the incoming IPMI packet 203 * 204 * @param[in] packet - Incoming IPMI packet 205 * @param[in] message - IPMI Message populated from the incoming packet 206 * @param[in] payloadLen - Length of the IPMI payload 207 * @param[in] session - session handle 208 * 209 */ 210 bool verifyPacketIntegrity(const std::vector<uint8_t>& packet, 211 const std::shared_ptr<Message>& message, 212 size_t payloadLen, 213 const std::shared_ptr<session::Session>& session); 214 215 /** 216 * @brief Add Integrity data to the outgoing IPMI packet 217 * 218 * @param[in] packet - Outgoing IPMI packet 219 * @param[in] message - IPMI Message populated for the outgoing packet 220 * @param[in] payloadLen - Length of the IPMI payload 221 */ 222 void addIntegrityData(std::vector<uint8_t>& packet, 223 const std::shared_ptr<Message>& message, 224 size_t payloadLen, 225 const std::shared_ptr<session::Session>& session); 226 227 /** 228 * @brief Decrypt the encrypted payload in the incoming IPMI packet 229 * 230 * @param[in] packet - Incoming IPMI packet 231 * @param[in] message - IPMI Message populated from the incoming packet 232 * @param[in] payloadLen - Length of encrypted IPMI payload 233 * @param[in] session - session handle 234 * 235 * @return on successful completion, return the plain text payload 236 */ 237 std::vector<uint8_t> 238 decryptPayload(const std::vector<uint8_t>& packet, 239 const std::shared_ptr<Message>& message, size_t payloadLen, 240 const std::shared_ptr<session::Session>& session); 241 242 /** 243 * @brief Encrypt the plain text payload for the outgoing IPMI packet 244 * 245 * @param[in] message - IPMI Message populated for the outgoing packet 246 * @param[in] session - session handle 247 * 248 * @return on successful completion, return the encrypted payload 249 */ 250 std::vector<uint8_t> 251 encryptPayload(const std::shared_ptr<Message>& message, 252 const std::shared_ptr<session::Session>& session); 253 254 } // namespace internal 255 256 } // namespace ipmi20parser 257 258 #ifdef RMCP_PING 259 namespace asfparser 260 { 261 262 // ASF message fields for RMCP Ping message 263 struct AsfMessagePing_t 264 { 265 struct parser::RmcpHeader_t rmcp; 266 267 uint32_t iana; 268 uint8_t msgType; 269 uint8_t msgTag; 270 uint8_t reserved; 271 uint8_t dataLen; 272 } __attribute__((packed)); 273 274 // ASF message fields for RMCP Pong message 275 struct AsfMessagePong_t 276 { 277 struct AsfMessagePing_t ping; 278 279 uint32_t iana; 280 uint32_t oemDefined; 281 uint8_t suppEntities; 282 uint8_t suppInteract; 283 uint32_t reserved1; 284 uint16_t reserved2; 285 } __attribute__((packed)); 286 287 /** 288 * @brief Unflatten an incoming packet and prepare the ASF message 289 * 290 * @param[in] inPacket - Incoming ASF packet 291 * 292 * @return ASF message in the packet on success 293 */ 294 std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket); 295 296 /** 297 * @brief Generate the ASF packet with the RMCP header 298 * 299 * @param[in] asfMsgTag - ASF Message Tag from Ping request 300 * 301 * @return ASF packet on success 302 */ 303 std::vector<uint8_t> flatten(uint8_t asfMsgTag); 304 305 } // namespace asfparser 306 #endif // RMCP_PING 307 308 } // namespace message 309