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