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