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